dpatel125
dpatel125

Reputation: 121

Redux state not being updated after dispatched actions

My redux state is not being properly updated after actions are dispatched. I am using redux and redux-thunk to make calls to an API and save it into a redux store. My state is supposed to hold a JSON file due to the fact that a lot of the JSON file will be used and it seems that none of the JSON file is being stored into the store. The problem is explained down at the bottom

This is my types.js file that define the action types:

export const FETCHING_REQUEST = "FETCHING_REQUEST";
export const FETCHING_SUCCESS = "FETCHING_SUCCESS";
export const FETCHING_FAILURE = "FETCHING_FAILURE";

The next file is my appActions.js file that hold the certain actions of the app. The comments in the code are from a different stackoverflow question that i never deleted.

import { FETCHING_SUCCESS, FETCHING_REQUEST, FETCHING_FAILURE } from "./types";

// Actions for the redux store

export const fetchingRequest = () => {
  return {
    type: FETCHING_REQUEST
  };
};

export const fetchingSuccess = json => {
  return {
    type: FETCHING_SUCCESS,
    payload: json
  };
};

export const fetchingFailure = error => {
  return {
    type: FETCHING_FAILURE,
    payload: error
  };
};

// Function will not work in a component
// Maybe the issue is redux
// more likely to be the Fetch not working in this function
export const fetchData = url => {
  console.log("Should enter async dispatch");
  return async dispatch => {
    dispatch(fetchingRequest());
    try{
      let response = await fetch(url);
      let json = await response.json();
      let dispatchChecker = dispatch(fetchingSuccess(json));
      console.log("JSON",json);
      //console.log(JSON.stringify(json, null, 2));
    }catch(error){
      console.log("ERROR",error);
      dispatch(fetchingFailure(error));
    }
  };
};

When being called in components of the app, only fetchData shall be called.

appReducer.js file

import {
  FETCHING_SUCCESS,
  FETCHING_REQUEST,
  FETCHING_FAILURE
} from "../actions/types";
import * as data from "./../../../../pickerdata.json"; // for debugging issues
import * as sample from "../../../../sampledata.json";
const initialState = {
  isFetching: false,
  errorMessage: "",
  articles: null
};

const appReducer = (state = initialState, action) => {
  switch (action.types) {
    case FETCHING_REQUEST:
      console.log("request from reducer");
      return { ...state, isFetching: true };
    case FETCHING_FAILURE:
      console.log("failure from reducer");
      return { ...state, isFetching: false, errorMessage: action.payload };
    case FETCHING_SUCCESS:
      console.log("success from reducer");
      return { ...state, isFetching: false, articles: action.payload };
    default:
      return state;
  }
};

export default appReducer;

index.js where the store is created

import { AppRegistry } from "react-native";
import App from "./App";
import { name as appName } from "./app.json";
import { Provider } from "react-redux";
import React, { Components } from "react";
import { createStore, applyMiddleware } from "redux";
import appReducer from "./src/data/redux/reducers/appReducer";
import thunk from "redux-thunk";

const store = createStore(appReducer, applyMiddleware(thunk));

store.subscribe(()=> {
  console.log("State Updated", store.getState());
})

console.log("Store", store.getState());
const AppContainer = () => (
  <Provider store={store}>
    <App />
  </Provider>
);

AppRegistry.registerComponent(appName, () => AppContainer);

This is the code to connect my store to components

    const mapStateToProps = state => {
      return { response: state };
    };

    const mapStateToDispatch = dispatch => ({
      fetchData: url => dispatch(fetchData(url))
    });

    export default connect(
      mapStateToProps,
      mapStateToDispatch
    )(Component);

The problem here is that the redux state is not being updated. Using the console, I know that the fetch call to the API is working because the JSON file will be shown in the console. Using store.subscribe and store.getState, I am able to see that the store does not change and that it stays the same as the the initial state described in the appReducer.js file.

for instance in the fetchData method in the appActions.js file. The first dispatch is to fetchingRequest and the redux store should look like this

{isFetching: true, errorMessage: "", articles: null }

but is instead like this

{isFetching: false, errorMessage: "", articles: null }

and the next dispatch after the fetch to the API is successful is the fetchingSuccess action and the redux store should look like this

{isFetching: false, errorMessage: "", articles: JSONfile }

but instead looks like this

{isFetching: false, errorMessage: "", articles: null }

Upvotes: 1

Views: 111

Answers (1)

unijob
unijob

Reputation: 180

In your types.js file:

Create a new type FETCHING_STATUS (for example)

In your fetchData function:

replace dispatch(fetchingRequest()); by

dispatch({type: FETCHING_STATUS, payload: { isFetching: true }});

replace dispatch(fetchingSuccess()); by

dispatch({type: FETCHING_STATUS, payload: {isFetching: false, articles: fetchingSuccess()}});

replace dispatch(fetchingFailed()); by

dispatch({type: FETCHING_STATUS, payload:  {isFetching: false, errorMessage: fetchingFailed()}});

In your appReducer.js:

import { combineReducers } from "redux";

function fetchingStatusReducer(state = {}, action) {
  switch (action.type) {
    case FETCHING_STATUS:
      return action.payload;
    default:
      return state;
  }
}

export default combineReducers({
  fetchingStatus: fetchingStatusReducer
});

Then store.getState().fetchingStatus will get updated as you want

Upvotes: 1

Related Questions