React Context Hooks vs Redux Hooks
Tags: react, redux, reacthooks, javascript
Published: 2019-12-13 11:42:56

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. 

{% codesandbox login-flow-w-redux-hooks-lnhb5 %}

{% codesandbox login-flow-w-react-context-api-p9j96 %}




## 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.

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

<Provider store={store}>
   <App />
</Provider>
```

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).

```jsx
<Provider value={/* some value, optional */}>
   <App />
</Provider>
```


## Consumer

### Get

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

```javascript
  const { isLoggedIn } = useSelector(state => ({
    isLoggedIn: state.isLoggedIn
  }));
```


Context provides `useContext` hook for this.

```javascript

// import context as AuthContext

const { isLoggedIn } = useContext(AuthContext);
```

### 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.


```javascript
const dispatch = useDispatch();
dispatch({
  type: SET_LOGIN_STATUS,
  isLoggedIn: true
});
```

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


```javascript
// import context as AuthContext

const { login } = useContext(AuthContext);
login();
```

## 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](https://codesandbox.io/s/login-flow-w-react-context-api-p9j96) on Codesandbox.

```javascript
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>
  );
```

### 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](https://codesandbox.io/s/login-flow-w-redux-hooks-lnhb5) 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.