I'm updating my first react/redux app to use redux-immutable
and can't figure out why the props in mapStateToProps
are empty. I see the properties populated in the thunk logger output but they are empty in the component.
components/Packages.jsx
:
import React from 'react';
import pureRender from 'pure-render-decorator';
import {connect} from 'react-redux';
import PropTypes from 'prop-types';
import {loadPackages} from '../../actions/packageActions';
import PackageList from './PackageList';
import ImmutablePropTypes from 'react-immutable-proptypes';
import {Map,fromJS,List} from 'immutable';
export class Packages extends React.Component {
constructor(props, context) {
super(props, context);
}
componentDidMount() {
this.props.dispatch(loadPackages());
}
render() {
return (
<div className="col-lg-12">
{this.props.results.length ?
<PackageList results={this.props.results} /> :
<h3>No Packages Available</h3>}
</div>
);
}
};
Packages.propTypes = {
results: ImmutablePropTypes.list.isRequired,
};
const mapStateToProps = (state, ownProps) => {
return {
packages: state.get('packages'),
results: !state.getIn(['packages','results']) ? List() : state.getIn(['packages','results'])
};
}
export const PackagesContainer = connect(mapStateToProps)(Packages);
actions/packageActions.jsx
:
import * as types from './actionTypes';
import PackageApi from '../api/packageApi';
export function loadPackages() {
return function(dispatch) {
return PackageApi.getAllPackages().then(packages => {
dispatch(loadPackagesSuccess(packages));
}).catch(error => {
throw(error);
});
};
}
export function loadPackagesSuccess(packages) {
return {
type: types.LOAD_PACKAGES_SUCCESS,
state: packages.data
}
}
reducers/packageReducer.js
:
import {Map,fromJS,List} from 'immutable';
import * as types from '../actions/actionTypes';
import initialState from './initialState';
export default function packageReducer(state = initialState, action) {
switch (action.type) {
case types.LOAD_PACKAGES_SUCCESS:
return state.set('packages', fromJS(action.state));
default:
return state;
}
}
reducers/initialState.js
:
import {Map, List} from 'immutable';
import update from 'immutability-helper';
const initialState = Map({
packages: Map({
totalCount: null,
results: List(),
dir: null,
totalPages: null,
limit: null,
sort: null,
page: null
})
});
export default initialState;
reducers/rootReducer.js
:
import {combineReducers} from 'redux-immutable';
import packages from './packageReducer';
import login from './loginReducer';
import { reducer as form } from 'redux-form/immutable';
const reducer = combineReducers({
packages,
login,
form
});
export default reducer;
store.js
:
import {createStore, applyMiddleware} from 'redux';
import {createLogger} from 'redux-logger';
import reducer from './reducers/rootReducer';
import thunk from 'redux-thunk';
import initialState from './reducers/initialState';
const store = createStore(reducer, initialState, applyMiddleware(thunk, createLogger()));
export default store;
thunk log
:
state:{
results: (10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
type: "LOAD_PACKAGES_SUCCESS"
}
Edit
Redux DevTools shows the correct data structure but mapStateToProps
still returns the empty List.
Redux DevTools:
{
packages
packages{
"totalCount": 145,
"results": [
{
Packages.jsx
:
const mapStateToProps = (state, ownProps) => {
return {
packages: state.get('packages'),
results: !state.getIn(['packages','packages','results']) ? List() : state.getIn(['packages','packages','results'])
};
}
I updated initialState
which fixes the issue with state.getIn(['packages','results']);
being undefined
. However, the results property still results in an empty list.
LOAD_PACKAGES_SUCCESS
action is correctly updating the store? And is thePackages
component being imported from the default (not named) export, to make sure it's wrapped inconnect
? – Shane Cavaliereimport {PackagesContainer} from './components/Package/Packages';
– neridaj