Skip to content

Commit cf4c96a

Browse files
committed
1 parent e14052a commit cf4c96a

File tree

10 files changed

+140
-27
lines changed

10 files changed

+140
-27
lines changed

src/App.tsx

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,30 @@
1+
import { useReducer } from "react";
12
import "./App.css";
23
import TodoForm from "./react-query/TodoForm";
34
import TodoList from "./react-query/TodoList";
5+
import Counter from "./state-management/Counter";
6+
import LoginStatus from "./state-management/LoginStatus";
7+
import TaskList from "./state-management/TaskList";
8+
import tasksReducer from "./state-management/reducers/tasksReducer";
9+
import NavBar from "./state-management/NavBar";
10+
import HomePage from "./state-management/HomePage";
11+
import TasksContext from "./state-management/contexts/tasksContext";
12+
import authReducer from "./state-management/reducers/authReducer";
13+
import AuthContext from "./state-management/contexts/authContext";
414

515

616
function App() {
17+
const [tasks, tasksDispatch] = useReducer(tasksReducer, []);
18+
const [user, authDispatch] = useReducer(authReducer, '');
19+
720
return (
8-
<>
9-
<TodoForm />
10-
<TodoList />
11-
</>
12-
)
21+
<AuthContext.Provider value={{ user, dispatch: authDispatch }}>
22+
<TasksContext.Provider value={{ tasks, dispatch: tasksDispatch }}>
23+
<NavBar />
24+
<HomePage />
25+
</TasksContext.Provider>
26+
</AuthContext.Provider>
27+
);
1328
}
1429

1530
export default App;

src/state-management/Counter.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
1-
import { useState } from 'react';
1+
import { useReducer, useState } from 'react';
2+
import counterReducer from './reducers/counterReducer';
23

34
const Counter = () => {
4-
const [value, setValue] = useState(0);
5+
6+
const [value, dispatch] = useReducer(counterReducer, 0);
57

68
return (
79
<div>
810
Counter ({value})
911
<button
10-
onClick={() => setValue(value + 1)}
12+
onClick={() => dispatch({ type: 'INCREMENT' })}
1113
className="btn btn-primary mx-1"
1214
>
1315
Increment
1416
</button>
1517
<button
16-
onClick={() => setValue(0)}
18+
onClick={() => dispatch({ type: 'RESET' })}
1719
className="btn btn-primary mx-1"
1820
>
1921
Reset

src/state-management/LoginStatus.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
1-
import { useState } from "react";
1+
import { useContext, useReducer, useState } from "react";
2+
import authReducer from "./reducers/authReducer";
3+
import AuthContext from "./contexts/authContext";
24

35
const LoginStatus = () => {
4-
const [user, setUser] = useState('');
6+
const {user, dispatch} = useContext(AuthContext);
57

68
if (user)
79
return (
810
<>
911
<div>
1012
<span className="mx-2">{user}</span>
11-
<a onClick={() => setUser('')} href="#">
13+
<a onClick={() => dispatch({ type: 'LOGOUT'})} href="#">
1214
Logout
1315
</a>
1416
</div>
1517
</>
1618
);
1719
return (
1820
<div>
19-
<a onClick={() => setUser('mosh.hamedani')} href="#">
21+
<a onClick={() => dispatch({ type: 'LOGIN', username: 'raf.avetisov'})} href="#">
2022
Login
2123
</a>
2224
</div>

src/state-management/NavBar.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1+
import { useContext } from 'react';
12
import LoginStatus from './LoginStatus';
3+
import TasksContext from './contexts/tasksContext';
24

35
const NavBar = () => {
6+
7+
const {tasks} = useContext(TasksContext);
8+
49
return (
510
<nav className="navbar d-flex justify-content-between">
6-
<span className="badge text-bg-secondary">4</span>
11+
<span className="badge text-bg-secondary">{tasks.length}</span>
712
<LoginStatus />
813
</nav>
914
);

src/state-management/TaskList.tsx

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
1-
import { useState } from 'react';
2-
3-
interface Task {
4-
id: number;
5-
title: string;
6-
}
1+
import { useContext, useReducer, useState } from 'react';
2+
import tasksReducer from './reducers/tasksReducer';
3+
import TasksContext from './contexts/tasksContext';
4+
import AuthContext from './contexts/authContext';
75

86
const TaskList = () => {
9-
const [tasks, setTasks] = useState<Task[]>([]);
10-
7+
const { tasks, dispatch } = useContext(TasksContext);
8+
const {user} = useContext(AuthContext);
119
return (
1210
<>
11+
<p>User: {user}</p>
1312
<button
1413
onClick={() =>
15-
setTasks([
16-
{ id: Date.now(), title: 'Task ' + Date.now() },
17-
...tasks,
18-
])
14+
dispatch({
15+
type: 'ADD',
16+
task: {
17+
id: Date.now(),
18+
title: 'Task ' + Date.now()
19+
}
20+
})
1921
}
22+
2023
className="btn btn-primary my-3"
2124
>
2225
Add Task
@@ -31,7 +34,10 @@ const TaskList = () => {
3134
<button
3235
className="btn btn-outline-danger"
3336
onClick={() =>
34-
setTasks(tasks.filter((t) => t.id !== task.id))
37+
dispatch({
38+
type: 'DELETE',
39+
taskId: task.id
40+
})
3541
}
3642
>
3743
Delete
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Dispatch } from "react";
2+
import { AuthAction } from "../reducers/authReducer";
3+
import React from "react";
4+
5+
interface AuthContextType {
6+
user: string;
7+
dispatch: Dispatch<AuthAction>;
8+
}
9+
10+
const AuthContext = React.createContext<AuthContextType>({} as AuthContextType);
11+
12+
export default AuthContext;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Dispatch } from "react";
2+
import { Task, TaskAction } from "../reducers/tasksReducer";
3+
import React from "react";
4+
5+
interface TasksContextType {
6+
tasks: Task[];
7+
dispatch: Dispatch<TaskAction>;
8+
}
9+
10+
const TasksContext = React.createContext<TasksContextType>({} as TasksContextType);
11+
12+
export default TasksContext;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
interface LoginAction {
3+
type: 'LOGIN';
4+
username: string;
5+
}
6+
7+
interface LogoutAction {
8+
type: 'LOGOUT';
9+
}
10+
11+
export type AuthAction = LoginAction | LogoutAction;
12+
13+
const authReducer = (state: string, action: AuthAction): string => {
14+
if (action.type === 'LOGIN') return action.username;
15+
if (action.type === 'LOGOUT') return '';
16+
return state;
17+
}
18+
19+
export default authReducer;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
interface Action {
3+
type: 'INCREMENT' | 'RESET';
4+
}
5+
6+
const counterReducer = (state: number, action: Action) => {
7+
if (action.type === 'INCREMENT') return state + 1;
8+
if (action.type === 'RESET') return 0;
9+
return state;
10+
}
11+
12+
export default counterReducer;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
2+
export interface Task {
3+
id: number;
4+
title: string;
5+
}
6+
7+
interface AddTask {
8+
type: 'ADD';
9+
task: Task;
10+
}
11+
12+
interface DeleteTask {
13+
type: 'DELETE';
14+
taskId: number;
15+
}
16+
17+
export type TaskAction = AddTask | DeleteTask;
18+
19+
const tasksReducer = (tasks: Task[], action: TaskAction): Task[] => {
20+
switch (action.type) {
21+
case 'ADD':
22+
return [action.task, ...tasks];
23+
case 'DELETE':
24+
return tasks.filter(t=> t.id !== action.taskId);
25+
}
26+
}
27+
28+
export default tasksReducer;

0 commit comments

Comments
 (0)