Last active
July 6, 2024 07:04
-
-
Save Armster15/15246545cef0baa91b3dd45715698e55 to your computer and use it in GitHub Desktop.
A basic React `useReducer` example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export enum TodoActionType { | |
ADD_TODO, | |
EDIT_TODO, | |
DELETE_TODO, | |
} | |
export type TodoState = { id: number; content: string }[]; | |
export type TodoAction = | |
| { | |
type: TodoActionType.ADD_TODO; | |
content: string; | |
} | |
| { | |
type: TodoActionType.EDIT_TODO; | |
id: number; | |
newContent: string; | |
} | |
| { | |
type: TodoActionType.DELETE_TODO; | |
id: number; | |
}; | |
// A reducer is merely a pure function that takes in the previous state and an action and returns the newly updated state | |
export function todoReducer(state: TodoState, action: TodoAction): TodoState { | |
switch (action.type) { | |
case TodoActionType.ADD_TODO: | |
return [...state, { id: Math.random(), content: action.content }]; | |
case TodoActionType.EDIT_TODO: | |
return state.map((todo) => { | |
if (todo.id === action.id) { | |
return { ...todo, content: action.newContent }; | |
} | |
return todo; | |
}); | |
case TodoActionType.DELETE_TODO: | |
return state.filter((todo) => todo.id !== action.id); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useReducer } from 'react'; | |
import { todoReducer, TodoActionType } from './todos'; | |
function App() { | |
const [state, dispatch] = useReducer(todoReducer, []); | |
function handleCreateNewTodo(ev: React.FormEvent<HTMLFormElement>) { | |
ev.preventDefault(); | |
const content = String(new FormData(ev.currentTarget).get('content')); | |
dispatch({ | |
type: TodoActionType.ADD_TODO, | |
content, | |
}); | |
} | |
function handleEditTodo(todoId: number) { | |
const newContent = prompt('Enter new content'); | |
dispatch({ | |
type: TodoActionType.EDIT_TODO, | |
id: todoId, | |
newContent, | |
}); | |
} | |
function handleDeleteTodo(todoId: number) { | |
dispatch({ | |
type: TodoActionType.DELETE_TODO, | |
id: todoId, | |
}); | |
} | |
return ( | |
<div> | |
<form onSubmit={handleCreateNewTodo}> | |
<label htmlFor="input">New todo</label> | |
<input required min="1" id="input" name="content" /> | |
<button>Submit</button> | |
</form> | |
<h2>Todos</h2> | |
{state.length > 0 ? ( | |
<ul> | |
{state.map((todo) => ( | |
<li key={todo.id}> | |
<span style={{ marginRight: '12px' }}>{todo.content}</span> | |
<button onClick={() => void handleEditTodo(todo.id)}>Edit</button> | |
<button onClick={() => void handleDeleteTodo(todo.id)}> | |
Delete | |
</button> | |
</li> | |
))} | |
</ul> | |
) : ( | |
<p>No todos (yet!)</p> | |
)} | |
</div> | |
); | |
} | |
export default App; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment