I'm building an application with React and Redux.
I have an Account component that fetches data from the server in the componentWillMount
method. While the data is being fetched, the component must show the "loading" text, so I've added the "isFetching" property to the account reducer. This property is set to true while data is fetching from the server.
The problem is, that while data is being fetched, the value of the "isFetching" property in the render
method is false, while at the same time the value of store.getState().account.isFetching
is true (as it must be). This causes the exception, because this.props.isFetching
is false, so the code is trying to show the this.props.data.protectedString
while the data
is still being loaded from the server (so it is null).
I assume that the mapStateToProps bind some wrong value (maybe the initial state), but I cannot figure out why and how can I fix it.
Here is my AccountView code:
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as actionCreators from '../../actions/account';
class AccountView extends React.Component {
componentWillMount() {
const token = this.props.token;
// fetching the data using credentials
this.props.actions.accountFetchData(token);
}
render() {
console.log("store state", window.store.getState().account); // isFetching == true
console.log("componentState", window.componentState); // isFetching == false
return (
<div>
{this.props.isFetching === true ? <h3>LOADING</h3> : <div>{this.props.data.protectedString}</div> }
</div>
);
}
}
const mapStateToProps = (state) => {
window.componentState = state.account;
return {
data: state.account.data,
isFetching: state.account.isFetching
};
};
const mapDispatchToProps = (dispatch) => {
return {
actions: bindActionCreators(actionCreators, dispatch)
};
};
export default connect(mapStateToProps, mapDispatchToProps)(AccountView);
Account reducer:
const initialState = {
data: null,
isFetching: false
};
export default function(state = initialState, action) {
switch (action.type) {
case ACCOUNT_FETCH_DATA_REQUEST:
return Object.assign({}, state, {
isFetching: true
});
case ACCOUNT_RECEIVE_DATA:
return Object.assign({}, state, {
data: action.payload.data,
isFetching: false
});
default:
return state;
}
}
Actions:
export function accountReceiveData(data) {
return {
type: ACCOUNT_RECEIVE_DATA,
payload: {
data
}
};
}
export function accountFetchDataRequest() {
return {
type: ACCOUNT_FETCH_DATA_REQUEST
};
}
export function accountFetchData(token) {
return (dispatch, state) => {
dispatch(accountFetchDataRequest());
axios({
// axios parameters to fetch data from the server
})
.then(checkHttpStatus)
.then((response) => {
dispatch(accountReceiveData(response.data));
})
.catch((error) => {
//error handling
});
};
}
This is how I'm creating the store:
import { applyMiddleware, compose, createStore } from 'redux';
import { routerMiddleware } from 'react-router-redux';
import rootReducer from '../reducers';
export default function configureStore(initialState, history) {
// Add so dispatched route actions to the history
const reduxRouterMiddleware = routerMiddleware(history);
const middleware = applyMiddleware(thunk, reduxRouterMiddleware);
const createStoreWithMiddleware = compose(
middleware
);
return createStoreWithMiddleware(createStore)(rootReducer, initialState);
}
And in index.js:
import { createBrowserHistory } from 'history';
import { syncHistoryWithStore } from 'react-router-redux';
import configureStore from './store/configureStore';
const initialState = {};
const newBrowserHistory = createBrowserHistory();
const store = configureStore(initialState, newBrowserHistory);
const history = syncHistoryWithStore(newBrowserHistory, store);
// for test purposes
window.store = store;
My code is based on this example - https://github.com/joshgeller/react-redux-jwt-auth-example
The code looks the same, but I've changed some places because of new versions of some modules.
isFetching
as false, andcomponentWillMoun
t is asynchronous, so probably, your initial state is wrong, why not check if data is null? – Icepickle