diff --git a/lab1/README.md b/lab1/README.md
index 581ae35..0b328d4 100644
--- a/lab1/README.md
+++ b/lab1/README.md
@@ -2,20 +2,18 @@
1. Skapa ett nytt projekt med create-react-app CLI
- 1. `$ npx create-react-app my-app`
+ 1. `$ npx create-react-app my-app`. _`npx` är en package runner för att köra npm-paket direkt från kommandoraden utan att behöva installera dem globalt_.
-2. Kör projektet
- 1. `$ cd my-app`
- 2. `$ npm start`
- 3. Nu bör ett browser-fönster med en grundapp i React öppnas.
- 4. Om du inte redan har React Developer Tools till din browser, ladda ner detta nu.
- [React Developer Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en)
-
+2. Kör projektet
+ 1. `$ cd my-app`
+ 2. `$ npm start`
+ 3. Nu bör ett browser-fönster med en grundapp i React öppnas.
+ 4. Om du inte redan har React Developer Tools till din browser, ladda ner detta nu.
+ [React Developer Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en)
3. Kolla runt i källkoden och fundera på/testa att...
- 1. Vad får jag out of the box?
- 2. Vilka paket är installerade?
- 3. Vilka beroenden har React?
- 4. Vilka komponenter existerar från början? ___Hint: React Devtools Extension___
- 5. Ersätt texten "Edit src/App.jsx and save to reload." med "Peace, Love & OP Web". Du behöver INTE kompilera om vid ändringar!
- 6. Lek runt lite!
-
+ 1. Vad får jag out of the box?
+ 2. Vilka paket är installerade?
+ 3. Vilka beroenden har React?
+ 4. Vilka komponenter existerar från början? **_Hint: React Devtools Extension_**
+ 5. Ersätt texten "Edit src/App.jsx and save to reload." med "Peace, Love & OP Web". Du behöver INTE kompilera om vid ändringar!
+ 6. Lek runt lite!
diff --git a/lab2/README.md b/lab2/README.md
index 487324a..c783c95 100644
--- a/lab2/README.md
+++ b/lab2/README.md
@@ -19,4 +19,5 @@ Från projektroten: `$ cd lab2`, `$ npm install` följt av `$ npm start`. Gå se
1. Hjälp en vän.
2. Utöka List-komponenten till att innehålla lite mer detaljerad användarinformation för varje item i listan.
-3. Ta en kaffe ☕️
+3. Testa att skapa och styla en egen komponent från grunden.
+4. Ta en kaffe ☕️
diff --git a/lab2/src/components/App/App.jsx b/lab2/src/components/App/App.jsx
index 03e394d..28d9ad1 100644
--- a/lab2/src/components/App/App.jsx
+++ b/lab2/src/components/App/App.jsx
@@ -16,7 +16,7 @@ const App = () => {
}, []);
const changeBackgroundColor = (e) => {
- // const color = e.target.value;
+ const color = e.target.value;
// TODO: Task 3 - change background color by setting state.
};
@@ -35,10 +35,7 @@ const App = () => {
-
+
);
};
diff --git a/lab2/src/components/List/List.jsx b/lab2/src/components/List/List.jsx
index a678423..f52496f 100644
--- a/lab2/src/components/List/List.jsx
+++ b/lab2/src/components/List/List.jsx
@@ -18,6 +18,7 @@ const List = ({ items = [], title }) => {
// TODO: Task 8: Set up filtering by declaring filteredItems.
// const filteredItems = ...
+
return (
{title}
diff --git a/lab3/DO_NOT_README.md b/lab3/DO_NOT_README.md
index 6b0b9fe..a96b061 100644
--- a/lab3/DO_NOT_README.md
+++ b/lab3/DO_NOT_README.md
@@ -4,7 +4,7 @@
### Task 2
-I `backgroundReducers.js`:
+I `avatarSlice.js`:
```javascript
const initialState = {
@@ -14,47 +14,64 @@ const initialState = {
### Task 3
-I `userActions.js`:
+I `avatarSlice.js`:
```javascript
- .then((users) => {
- dispatch({
- type: USERS_RECEIVED,
- payload: users
- })
- })
+const avatarSlice = createSlice({
+ name: "avatar",
+ initialState,
+ reducers: {
+ updatedAvatar: (state, action) => {
+ state.currentAvatar = action.payload;
+ },
+ },
+});
```
### Task 4
-I `userReducers.js`:
+I `avatarSlice.js`:
```javascript
- ...
- case USERS_RECEIVED:
- return {
- all: action.payload,
- error: null
- };
- ...
+const avatarSlice = createSlice({
+ name: "avatar",
+ initialState,
+ reducers: {
+ updatedAvatar: (state, action) => {
+ state.currentAvatar = action.payload;
+ },
+ resetAvatar: (state, action) => {
+ state.currentAvatar = null;
+ },
+ },
+});
+...
+...
+export const { updatedAvatar, resetAvatar } = avatarSlice.actions;
```
### Task 5
-I `Container.jsx`:
+I `AvatarPicker.jsx`:
```javascript
-useEffect(() => {
- dispatch(getAllUsers());
-}, []);
+const dispatch = useDispatch();
+
+const handleOnClick = (avatar) => {
+ dispatch(updatedAvatar(avatar));
+};
+
+const handleOnReset = () => {
+ dispatch(resetAvatar());
+};
```
### Task 6
-I `List.jsx`:
+I `NavBar.jsx`:
```javascript
-const users = useSelector((state) => state.users.all);
+const avatar = useSelector(selectCurrentAvatar);
```
## Del 2
diff --git a/lab3/README.md b/lab3/README.md
index bb5cc84..a93c1a1 100644
--- a/lab3/README.md
+++ b/lab3/README.md
@@ -7,24 +7,24 @@ Från projektroten: `$ cd lab3`, `$ npm install` följt av `$ npm start`. Gå se
## Del 1 - Redux-snurran
1. Ta en till på befintliga komponenter och hur Redux-snurran är implementerad för att välja bakgrund. Ladda ner och använd [Redux DevTools](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd) för detta.
-2. Bakgrundsfärgen är satt till `lavender` från början via initialState. Byt default från `lavender` till `gold`._Hint: Detta görs i en reducer_
-3. Användarna visas inte i listan just nu. Börja med att dispatcha ett action när användare har hämtats asynkront i `userActions`.
-4. När vi har dispatchat en action måste vi hantera den i våra reducers. Öppna `userReducers.js` och stoppa in resultatet från din nya action i applikationens state.
-5. I `Container.jsx` har vi nu möjlighet att dipatcha actions tack vare vår hooks `useDispatch()`. Vi vill här hämta alla användare när komponenten mountas i `useEffect()` med vår nyss implementerade action creator. Implementera detta och bekräfta att det fungerar med Redux Dev Tools.
-6. Nu när vi har användaren i vår store vill vi kunna läsa dom i komponenten `List.jsx`. Deklarera konstanten `users` i `List.jsx` med hjälp av `useSelector()`. Just nu är den bara en tom array. _Hint: Hur används `useSelector()` i `container.js`?_
+2. Bakgrundsfärgen är satt till `lavender` från början via initialState. Byt default från `lavender` till `gold`._Hint: Detta görs i en slice_
+3. Vår applikation har fått ny feature, en avatar-väljare. Men just nu fungererar den inte alls. Det ska vi fixa med Redux! Börja med att göra klart logien för att uppdatera vårt state i action-funktionen `updatedAvatar` i `avatarSlice.js`.
+4. Lägg även till ytterligare en ny action i `avatarSlice.js` som nollställer `currentAvatar`. Glöm inte bort att exportera den tillsammans med `updatedAvatar`!
+5. Nu vill vi dispatch:a våra två nya actions från `AvatarPicker.jsx`. Kontrollera att det fungerar med Redux Dev Tools. Du ska nu kunna se actions som skickas och att vårt state uppdateras.
+6. Nu när vi har rätt värde i vår store kan vi läsa ut det vart vi vill. Använd `useSelector()` i `NavBar.jsx` för att välja ut vår avatar. Deklarera om konstanten `avatar`.
7. Nu ska applikationen fungera fullt ut!
## Del 2 - Egen komponent
-Nu är det dags att sätta allt du lärt dig hittills på prov. Gör så långt du hinner. Uppgiften är att du ska skapa en egen komponent och visa detaljerad användarinformation i denna. I `List.jsx` finns det nu en callback, `onClick`, som kommer att skicka med ett id för användaren som klickades på. I `api.js` finns det en funktion som hämtar användardata baserat på ett id.
+Nu är det dags att sätta allt du lärt dig hittills på prov. Gör så långt du hinner. Uppgiften är att du ska skapa en egen komponent och visa detaljerad användarinformation i denna när man klickat på en av användarna i listan. I `List.jsx` finns det nu en callback, `onClick`, som kommer att skicka med ett id för användaren som klickades på. I `api.js` finns det en funktion som hämtar användardata baserat på ett id.
För att lösa uppgiften behöver du:
- Skapa en ny komponent `` (eller liknande namn) och använda denna i `Container.jsx`.
- `` behöver rendera ut JSX för detaljerad användardata.
-- Skapa en ny action creator i `userActions.js` som tar in ett id och gör ett asynkront anrop mot `api.js` för att hämta ut detaljerad användardata.
-- Utöka state för `userReducers.js` till att även innehålla detaljerad användardata och hantera en ny typ av inkommande action.
-- Dispatcha ett nytt action för detaljerad användardata från `onItemClick()` i `List.jsx` via `useDispatch()`.
+- Skapa en ny action `userSlice.js` som tar in ett id och gör ett asynkront anrop mot `api.js` för att hämta ut detaljerad användardata för en användare.
+- Utöka state i `userSlice.js` till att även innehålla detaljerad användardata.
+- Dispatcha en nytt action för detaljerad användardata från `onItemClick()` i `List.jsx` via `useDispatch()`.
- Läsa in den detaljerade användardatan från applikationens state till din nya komponent.
##### _Del två finns löst i solutions-branchen om du bara vill se lösningen_ 😇
diff --git a/lab3/src/actions/backgroundActions.js b/lab3/src/actions/backgroundActions.js
deleted file mode 100644
index 0a686dc..0000000
--- a/lab3/src/actions/backgroundActions.js
+++ /dev/null
@@ -1,10 +0,0 @@
-export const SET_BG_COLOR = "SET_BG_COLOR";
-
-export const setBackgroundColor = (color) => {
- return {
- type: SET_BG_COLOR,
- payload: {
- color
- }
- };
-};
\ No newline at end of file
diff --git a/lab3/src/actions/userActions.js b/lab3/src/actions/userActions.js
deleted file mode 100644
index 283ff4d..0000000
--- a/lab3/src/actions/userActions.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import { getUsers } from '../api';
-
-export const USERS_RECEIVED = "USERS_RECEIVED";
-export const GET_USERS_ERROR = "GET_USERS_ERROR";
-
-export const getAllUsers = () => {
- /*
- Actions should generally be POJO (Plain JavaScript Object), but getting the users is made
- asynchronously.
- Thanks to the thunk middleware (declared in store.js) we can handle asynchronous events
- in our actions.
- */
- return dispatch => {
- getUsers() // Gets users from our API and returns a promise.
- .then((users) => {
- // TODO: Task 3 - Dispatch an action of type USERS_RECEIVED and payload: users.
- })
- .catch((e) => {
- dispatch({
- type: GET_USERS_ERROR,
- payload: {
- error: e
- }
- });
- })
- };
-};
diff --git a/lab3/src/components/App/App.jsx b/lab3/src/components/App/App.jsx
index d69530c..1a1029e 100644
--- a/lab3/src/components/App/App.jsx
+++ b/lab3/src/components/App/App.jsx
@@ -1,13 +1,10 @@
import React from "react";
import Container from "../Container/Container";
import { Provider } from "react-redux";
-import configureStore from "../../store";
+import store from "../../store";
import "./App.css";
-const preloadedState = window.__PRELOADED_STATE__;
-const store = configureStore(preloadedState);
-
const App = () => (
diff --git a/lab3/src/components/AvatarPicker/AvatarPicker.css b/lab3/src/components/AvatarPicker/AvatarPicker.css
new file mode 100644
index 0000000..a7917b3
--- /dev/null
+++ b/lab3/src/components/AvatarPicker/AvatarPicker.css
@@ -0,0 +1,4 @@
+.buttonContainer {
+ display: flex;
+ gap: 10px;
+}
\ No newline at end of file
diff --git a/lab3/src/components/AvatarPicker/AvatarPicker.jsx b/lab3/src/components/AvatarPicker/AvatarPicker.jsx
new file mode 100644
index 0000000..58707ec
--- /dev/null
+++ b/lab3/src/components/AvatarPicker/AvatarPicker.jsx
@@ -0,0 +1,42 @@
+import React from "react";
+import { useDispatch } from "react-redux";
+import {
+ resetAvatar,
+ updatedAvatar,
+ selectCurrentAvatar,
+} from "../../features/avatar/avatarSlice";
+import "./AvatarPicker.css";
+
+const AvatarPicker = () => {
+ const dispatch = useDispatch();
+
+ const handleOnClick = (avatar) => {
+ // TODO: Task 5 - dispatch
+ };
+
+ const handleOnReset = () => {
+ // TODO: Task 5 - dispatch
+ };
+
+ return (
+
+
Välj avatar
+
+
+
+
+
+
+
+ );
+};
+
+export default AvatarPicker;
diff --git a/lab3/src/components/BackgroundColorPicker/BackgroundColorPicker.jsx b/lab3/src/components/BackgroundColorPicker/BackgroundColorPicker.jsx
index fa2498d..46dbd3d 100644
--- a/lab3/src/components/BackgroundColorPicker/BackgroundColorPicker.jsx
+++ b/lab3/src/components/BackgroundColorPicker/BackgroundColorPicker.jsx
@@ -1,14 +1,14 @@
import React from "react";
import { useDispatch } from "react-redux";
-import { setBackgroundColor } from "../../actions/backgroundActions";
import colors from "./colors";
+import { updatedBackgroundColor } from "../../features/background/backgroundSlice";
import "./BackgroundColorPicker.css";
const BackgroundColorPicker = () => {
const dispatch = useDispatch();
const handleOnChange = (e) => {
- dispatch(setBackgroundColor(e.target.value));
+ dispatch(updatedBackgroundColor(e.target.value));
};
return (
diff --git a/lab3/src/components/Container/Container.jsx b/lab3/src/components/Container/Container.jsx
index cdc415b..b7407db 100644
--- a/lab3/src/components/Container/Container.jsx
+++ b/lab3/src/components/Container/Container.jsx
@@ -1,38 +1,46 @@
import React, { useEffect } from "react";
import BackgroundColorPicker from "../BackgroundColorPicker/BackgroundColorPicker";
import List from "../List/List";
+import AvatarPicker from "../AvatarPicker/AvatarPicker";
import { useDispatch, useSelector } from "react-redux";
-import { getAllUsers } from "../../actions/userActions";
+import { selectBackgroundColor } from "../../features/background/backgroundSlice";
+import { fetchUsers } from "../../features/users/usersSlice";
import "./Container.css";
+import NavBar from "../NavBar/NavBar";
const Container = () => {
const dispatch = useDispatch();
- const backgroundColor = useSelector((state) => state.background.bgColor);
+ const backgroundColor = useSelector(selectBackgroundColor);
- // TODO: Task 5 - Get all users upon mounting the component
- useEffect(() => {}, []);
+ useEffect(() => {
+ dispatch(fetchUsers());
+ }, []);
return (
-
-
-
Lab 3
-
-
- 👩💻
- {" "}
- Öppna upp README.md och följ instruktionerna{" "}
-
- 👨💻
-
-
+ <>
+
+
+
+
Lab 3
+
+
+ 👩💻
+ {" "}
+ Öppna upp README.md och följ instruktionerna{" "}
+
+ 👨💻
+
+