0

I am like in a strange problem. The problem is that I am trying to make an API hit (in service file) which in turn provides some data (it is working), this data is to be updated in my reducer1.js and then returned. Now, my issue is though the value is coming in reducer file, but is not returned, so in turn, state is not changed, and in turn my end component is not rerendered.

Now, when my service file is successfully hitting and then returning data to my reducer1.js, why in the world the updated-state is not returned by "GET_List" action type? Can someone see any problem?

index.js (service file)

const global = {
  getActressList: async function(){
    const response = await fetch("http://localhost:2000/api/actressList");
    const data = await response.json();
    return data;
  }
}

export default global;

reducer1.js

import global from '../../services/index';

const initialState = {
  data: [
    {
      id: 1, 
      name: "Aishwarya Rai",
      src: "/assets/img/aishwarya.png"
    }
  ]
};

function reducer1(state = initialState, action) {

  switch (action.type) {

    case "GET_LIST": {
      const data = global.getActressList();
      data.then((res)=> {
        return {
          ...state,
          data: res
        }
      })
    }
    default:
      return state;
  }
}

export default reducer1;

Result:

enter image description here

Deadpool
  • 7,811
  • 9
  • 44
  • 88
  • Apart from the fact that you're not returning anything from the `"GET_LIST"` reducer, there should NOT be async, side effect code inside a reducer. They are meant to be pure. The API response data should be passed to the reducer by the action. Either do the API call in the component and pass result to the action, or do the async stuff in the action (in which case you'll need something like `redux-thunk`, since async stuff in actions isn't supported by default in Redux). See this: https://stackoverflow.com/questions/49155438/react-redux-is-adding-async-method-in-a-reducer-an-anti-pattern – Jayce444 Jul 18 '20 at 12:22
  • @Deadpool You are returning from a promise not from a reducer function... – Rostyslav Jul 18 '20 at 12:23
  • @Rostyslav - pls can you help with the correct code. That is my problem, I am getting promise and later on ... when even I can see data on hovering (res) in reducer, it doesn't change the state or return anything! ;( – Deadpool Jul 18 '20 at 12:24

1 Answers1

1

You are returning from a promise not from a reducer function:

function reducer1(state = initialState, action) {
  switch (action.type) {
    case "GET_LIST": {
      const data = global.getActressList();
      data.then((res) => {
        // here you are returning from a promise not from a reducer function
        return {
          ...state,
          data: res,
        };
      });
    }
    default:
      return state;
  }
}

The code in reducer should be sync like this:

function reducer1(state = initialState, action) {
  switch (action.type) {
    case "GET_LIST": {
      return {
        ...state,
        data: action.payload,
      };
    }
    default:
      return state;
  }
}

And your data fetching should be moved to component effect like this:

function YourComponent() {
  const dispatch = useDispatch();
  const data = useSelector(state => state.data)

  useEffect(() => {
    const data = global.getActressList();
    data.then((res) => {
      dispatch({type: 'GET_LIST', payload: res});
    });
  }, [])

  ...
}

EDIT

If you use class components the fetching logic should be placed in componentDidMount lifecycle hook like this:

class YourComponent extends Component {
  state = { data: [] };

  componentDidMount() {
    const data = global.getActressList();
    data.then((res) => {
      dispatchYourAction({type: 'GET_LIST', payload: res});
    });
  }

  ...
}
Rostyslav
  • 2,606
  • 9
  • 17
  • Instead of useEffect, if I am using a "Class Component" then where should code inside the `useEffect` be written? – Deadpool Jul 18 '20 at 12:31
  • 1
    @Deadpool it should go to `componentDidMount` like in the updated answer. `dispatchYourAction` is your custom action creator which you should add. Just see the [docs reference](https://react-redux.js.org/using-react-redux/connect-mapdispatch) – Rostyslav Jul 18 '20 at 12:40
  • 1
    @Deadpool in class component case you also access data through `props` instead. See the [mapStateToProps](https://react-redux.js.org/using-react-redux/connect-mapstate) – Rostyslav Jul 18 '20 at 12:42