Skip to content

Instantly share code, notes, and snippets.

@Armster15
Last active July 6, 2024 07:04
Show Gist options
  • Save Armster15/15246545cef0baa91b3dd45715698e55 to your computer and use it in GitHub Desktop.
Save Armster15/15246545cef0baa91b3dd45715698e55 to your computer and use it in GitHub Desktop.
A basic React `useReducer` example
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);
}
}
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