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 🙂