I'm wondering what the recommended best practice is for manipulating and exposing the new React Context.
The easiest way to manipulate context state seems to be to just attach a function to the context that either dispatches (usereducer
) or setstate (useState
) to change its internal value once called.
export const TodosProvider: React.FC<any> = ({ children }) => {
const [state, dispatch] = useReducer(reducer, null, init);
return (
<Context.Provider
value={{
todos: state.todos,
fetchTodos: async id => {
const todos = await getTodos(id);
console.log(id);
dispatch({ type: "SET_TODOS", payload: todos });
}
}}
>
{children}
</Context.Provider>
);
};
export const Todos = id => {
const { todos, fetchTodos } = useContext(Context);
useEffect(() => {
if (fetchTodos) fetchTodos(id);
}, [fetchTodos]);
return (
<div>
<pre>{JSON.stringify(todos)}</pre>
</div>
);
};
I was however told exposing and using the react context object directly is probably not a good idea, and was told to wrap it inside a hook instead.
export const TodosProvider: React.FC<any> = ({ children }) => {
const [state, dispatch] = useReducer(reducer, null, init);
return (
<Context.Provider
value={{
dispatch,
state
}}
>
{children}
</Context.Provider>
);
};
const useTodos = () => {
const { state, dispatch } = useContext(Context);
const [actionCreators, setActionCreators] = useState(null);
useEffect(() => {
setActionCreators({
fetchTodos: async id => {
const todos = await getTodos(id);
console.log(id);
dispatch({ type: "SET_TODOS", payload: todos });
}
});
}, []);
return {
...state,
...actionCreators
};
};
export const Todos = ({ id }) => {
const { todos, fetchTodos } = useTodos();
useEffect(() => {
if (fetchTodos && id) fetchTodos(id);
}, [fetchTodos]);
return (
<div>
<pre>{JSON.stringify(todos)}</pre>
</div>
);
};
I have made running code examples for both variants here: https://codesandbox.io/s/mzxrjz0v78?fontsize=14
So now I'm a little confused as to which of the 2 ways is the right way to do it?
getTodos
is just a function that cannot change, does it make sense to use that as update argument inuseMemo
? Also how would you handle an initial effect. Say if you were to call `getTodos´ in useEffect hook when provider mounts? Could you memorize that call as well? – Felicio