DEV Community

andy_801 πŸ”«πŸ‡ΊπŸ‡¦
andy_801 πŸ”«πŸ‡ΊπŸ‡¦

Posted on

React Context Hooks vs Redux Hooks

Here I was trying to implement the same login routine with Redux and Context Provider. Both doing it in the pretty same way and with similar syntax.

Provider

First of all, you need to provide access to the state. Redux and Context doing it with a component called Provider.

Redux Provider accepts prop called store, with current state and rules on how to update it.

const store = createStore(/* rules to set store */)

<Provider store={store}>
   <App />
</Provider>
Enter fullscreen mode Exit fullscreen mode

Context Provider accepts value which can be passed down to Consumer. But you also free to rewrite this Provider to customize it (this is actually what we want).

<Provider value={/* some value, optional */}>
   <App />
</Provider>
Enter fullscreen mode Exit fullscreen mode

Consumer

Get

Redux provides useSelector hook to get value from the state you interested in.

  const { isLoggedIn } = useSelector(state => ({
    isLoggedIn: state.isLoggedIn
  }));
Enter fullscreen mode Exit fullscreen mode

Context provides useContext hook for this.


// import context as AuthContext

const { isLoggedIn } = useContext(AuthContext);
Enter fullscreen mode Exit fullscreen mode

Set

You can also update the state.

Redux provides you with a dispatch method that triggers store updates. Ofc, you need to write these rules yourself within reducer.

const dispatch = useDispatch();
dispatch({
  type: SET_LOGIN_STATUS,
  isLoggedIn: true
});
Enter fullscreen mode Exit fullscreen mode

With React Context you need to implement update method within Provider and then use it via same useContext hook;

// import context as AuthContext

const { login } = useContext(AuthContext);
login();
Enter fullscreen mode Exit fullscreen mode

Business Logic

Context Provider

Here is Context Provider implementation with state and functions to update it. In the end, you need to pass it further within value property to make it available to the Consumer. Looks pretty sharp and simple to me.
Check for full code for Context on Codesandbox.

export const AuthContext = React.createContext(null);

const initialState = {
  isLoggedIn: false,
  isLoginPending: false,
  loginError: null
}

export const ContextProvider = props => {
  const [state, setState] = useState(initialState);

  const setLoginPending = (isLoginPending) => setState({
    ...state,
    isLoginPending
  });
  const setLoginSuccess = (isLoggedIn) => setState({
    ...state,
    isLoggedIn
  });
  const setLoginError = (loginError) => setState({
    ...state,
    loginError
  });

  const login = (email, password) => {
    setLoginPending(true);
    setLoginSuccess(false);
    setLoginError(null);

    fetchLogin( email, password, error => {
      setLoginPending(false);

      if (!error) {
        setLoginSuccess(true);
      } else {
        setLoginError(error);
      }
    })
  }

  return (
    <AuthContext.Provider
      value={{
        state,
        login,
        logout,
      }}
    >
      {props.children}
    </AuthContext.Provider>
  );
Enter fullscreen mode Exit fullscreen mode

Redux Store

With Redux you need to write a bit more lines of code. And add thunk middleware if you want to make it work async, and most times probably you are. There are a lot of articles around on how to do it, so I will skip full codebase, you can check full code for Redux on Codesandbox.

Outro

So it looks like this Context and Redux hooks can be used interchangeably, and also it can be easily used together. Like for example, Redux for the main store and Context for some more local state management. So, you won't put all your data in same store which can become very messy at the end.

Top comments (0)