React context reducer
A simple ToDo app to feel the well known React context in a reducer pattern.
The ToDo class:
class ToDo{ id: number = Math.floor(Math.random() * 10000); title: string; done: boolean = false; constructor(title){ this.title = title; } }
The Context, context provider & context reducer
const ToDoContext = React.createContext<ToDoContextProps>(); const contextReducer = (state:Array<ToDo>, action)=>{ const index = state.findIndex(todo => todo.id == action.id); switch(action.type){ case 'SET-TITLE': state[index].title = action.title; break; break case 'TOGGLE': state[index] = {...state[index],done : !state[index].done}; break; case 'ADD-TODO': state.push(new ToDo('new to do')) } return [...state]; } const MyContextProvider = ({children}) => { const [todoState,todoReducer] = React.useReducer(contextReducer,[new ToDo('First do I do')]); const value = {todoState,todoReducer}; return <ToDoContext.Provider value={value}>{children}</ToDoContext.Provider> }
Last: the React app
const ToDoComp:React.FC<ToDoCompProp> = React.memo(({toDo, todoReducer}) => { const isDone = {textDecoration: toDo.done?'line-through':''} return <p style={isDone} onClick={()=>todoReducer({type:'TOGGLE',id:toDo.id})}><EditTitle title={toDo.title} callback={title=>todoReducer({type:'SET-TITLE',id:toDo.id,title:title})} /></p> }) const ToDoList: React.FC = ()=>{ const {toDos,todoReducer} = React.useContext(ToDoContext); return <> {toDos.map(todo => <ToDoComp key={todo.id} toDo={todo} todoReducer={todoReducer} />)} <button onClick={()=>todoReducer({type:'ADD-TODO'})}>Add ToDo</button> </> } const Count: React.FC = ()=>{ const {toDos,todoReducer} = React.useContext(ToDoContext); return <p>Count: {toDos.length}</p> } const App: React.FC = () => { return <MyContextProvider> <Count /> <ToDoList /> </MyContextProvider> }
Conclusion
Nice 🙂