
Posted on • Edited on • Originally published atnotes.furkanozbek.com
React hooks: useContext
State Management
While developing React application, you are most likely will have different pages, components to render. In this case most components itself has the hooks we can use(functional components) to create component state. And you also pass some internal state as a prop to subcomponents.
// components/TodoList.jsconstTodoList=()=>{const[todoList,setTodoList]=useState([]);const[user,setUser]=useState({})return(<><Headeruser={user}/><Bodyuser={user}/><Footeruser={user}/>{todoList.map(todo=><Todotodo={todo}key={todo.id}user={user}/>)}</>);}
Context API
React Context is a state management API which is in the React's core package. We can use Context API for pretty much anything that we need from state manegement library. Main purpose of using it is sharing data across multiple components without passing them via props.
All context consumers arere-rendered whenever a value passed to the Provider changes. One way to fix this is to use useMemo hook which wouldmemoize the value object. It would only be re-created whendependency value changes.
In this article we will try to manage our todoList using Context API
Creating TodoListContext
// contexts/todoListContext.jsconstTodoListContext=createContext([]);constTodoListContextProvider=(props)=>{const[todoList,setTodoList]=useState([]);// Only rerender when todoList changesconstvalue=useMemo(()=>[todoList,setTodoList],[todoList]);return(<TodoListContext.Providervalue={value}>{props.children}</TodoListContext.Provider>)}
We can also create a custom hook and manage some logic inside of our hook.
// contexts/todoListContext.jsconstuseTodoList=()=>{constcontext=useContext(TodoListContext);if(!context){thrownewError("useTodoList must be used inside TodoListProvider")}returncontext;}
After that we can use this hook in the components
// components/TodoList.jsconstTodoList=()=>{const[todoList,setTodoList]=useTodoList();constaddTodo=(todo)=>setTodoList([...todoList,todo]);return(<>{todoList.map(todo=><Todotodo={todo}key={todo.id}/>)}<buttononClick={()=>{addTodo({id:Math.random(),name:"New Todo"})}}>Add Todo</button></>);}
Then what we can do to improve the hook is tha we can remove any external logic from components and adding them to the hook itself. So we can remove addTodo function from here and move it to the useTodoList hook. And we can also use useReducer instead of useState in this situation.
useReducer can reduce the complexity of the actions and increase usability
// contexts/todoListContext.jsconsttodoReducer=(state,action)=>{switch(action.type){case"NEW":return[...state,action.payload]case"DELETE":returnstate.filter(todo=>todo.id!=action.payload);default:returnstate;}}constuseTodoList=()=>{constcontext=useContext(TodoListContext);if(!context){thrownewError("useTodoList must be used inside TodoListProvider")}const[todoList,setTodoList]=context;// Hook FunctionsconstaddTodo=(todo)=>dispatch({type:"NEW",payload:todo})constremoveTodo=(todoId)=>dispatch({type:"DELETE",payload:todoId});return{todoList,setTodoList,addTodo,removeTodo};}
Final code will look like this;
constTodoListContext=createContext([]);consttodoReducer=(state,action)=>{switch(action.type){case"NEW":return[...state,action.payload]case"DELETE":returnstate.filter(todo=>todo.id!=action.payload);default:returnstate;}}constTodoListContextProvider=(props)=>{const[state,dispatch]=useReducer(todoReducer,[]);constvalue=useMemo(()=>[state,dispatch],[state]);return(<TodoListContext.Providervalue={value}>{props.children}</TodoListContext.Provider>)}constuseTodoList=()=>{constcontext=useContext(TodoListContext);if(!context){thrownewError("useTodoList must be used inside TodoListProvider")}const[state,dispatch]=context;// Hook FunctionsconstaddTodo=(todo)=>dispatch({type:"NEW",payload:todo})constremoveTodo=(todoId)=>dispatch({type:"DELETE",payload:todoId});return{todos:state,dispatch,addTodo,removeTodo};}export{TodoListContextProvider,useTodoList
Reference
Application State Management with React
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse