How to handle side effects when migrating from Redux to React Context API + hooks
Asked Answered
S

2

8

If you have a Redux Application which you'd like to migrate to the new React Context API + hooks (useReducer) how would you replace redux-saga or redux-thunk for handling side effects? Let's take the example from redux-saga's github page:

import { call, put, takeEvery, takeLatest } from 'redux-saga/effects'
import Api from '...'

function* fetchUser(action) {
   try {
      const user = yield call(Api.fetchUser, action.payload.userId);
      yield put({type: "USER_FETCH_SUCCEEDED", user: user});
   } catch (e) {
      yield put({type: "USER_FETCH_FAILED", message: e.message});
   }
}

function* mySaga() {
  yield takeEvery("USER_FETCH_REQUESTED", fetchUser);
}

function* mySaga() {
  yield takeLatest("USER_FETCH_REQUESTED", fetchUser);
}

export default mySaga;

What is the recommended best practice for doing the equivalent without Redux, but using the React Context api + hooks instead?

Siglos answered 3/4, 2019 at 17:50 Comment(2)
you can use regular method like fetch or axios for handle sync and Async request in non-redux application.Manysided
There's no best practice, useReducer is barebone. Side effects likely will happen in useEffect, unless you will come up with some superstructure similar to Saga.Clova
S
4

Take a look at useEffect hook. This is what you use for side-effects.

https://reactjs.org/docs/hooks-effect.html

Here is an example of how to call an api from your component and render the data:

import ReactDOM from "react-dom";
import React, { useState, useEffect } from "react";
import axios from "axios";

function SearchResults() {
  const [data, setData] = useState(null);
  useEffect(() => {
    function getFetchUrl() {
      return "https://hn.algolia.com/api/v1/search?query=react";
    }
    async function fetchData() {
      console.log("asdasd");
      const result = await axios(getFetchUrl());
      setData(result.data);
    }

    fetchData();
  }, []);
  return <div>{JSON.stringify(data)}</div>;
}

ReactDOM.render(<SearchResults />, document.getElementById("root"));

I partially took this code from overreacted.io, I strongly suggest you read this amazing article about useEffect hook: https://overreacted.io/a-complete-guide-to-useeffect/

Regarding useReducer, it's basically a useState on steroids. It allows you to handle more complex state operations, but there isn't a big difference really.

In the case you want state to be shared by different components, you may use useContext but its really unrelated on how the side-effects work.

---- about redux:

I just want to comment also that moving to use React Context api + hooks to replace redux in your app could be good if you just use it for passing data to nested components, for example. But if you want all the great tooling, middleware, devtools, etc, Redux is still a great choice, even with hooks, they are not mutually exclusive.

See:

https://blog.isquaredsoftware.com/2019/03/presentation-state-of-redux/ Specifically https://blog.isquaredsoftware.com/presentations/2019-03-state-of-redux/#/10 https://blog.isquaredsoftware.com/presentations/2019-03-state-of-redux/#/11

Sunbreak answered 3/4, 2019 at 18:8 Comment(1)
This answers the question of side-effects for components, but I think the original question was about side-effects in terms of global state.Braca
S
2

If you have a Redux Application which you'd like to migrate to the new React Context API, you need to be able to get data to any component in your hierarchy, you need to be able to separate your view logic from your business logic and you need to be able to split up the business logic, meaning modularity, meaning not have 1000 LOCs in a single file.

Unless you have no other choice, I would stick with Redux. With Redux you get excellent documentation, the docs are pretty well written and you can generally understand whats going on. The design patterns are well-known and their is enough support and open-source libraries specifically made to work with Redux.

With Context, you don't have to use a separate library, that's about it. That's the only benefit to using Context in place of Redux. Context has its own challenges because of cross-cutting concerns when building the store.

Sapsucker answered 27/6, 2019 at 2:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.