SirFry SirFry - 26 days ago 16
React JSX Question

React / Redux - mapStateToProps

I'm pulling data in my action from a mongo api. I can console.log the data in the action but I can't get it to map to the components props. I just see an empty array. I'm new to react and redux so it's probably something simple I'm misunderstanding. Aside from my question and other links to good reads about this you would recommend would be amazing :) Thanks a ton guys!

StoreLoader Component

import React, { Component } from 'react'
import { connect } from 'react-redux'

import storeData from '../data/storeData'

import { loadStoresFromServer } from '../actions'


class StoreLoader extends Component {

componentWillMount() {
this.props.dispatch(loadStoresFromServer())
console.log(this.props.data)
}


loadStores() {
return (
<div className="row loaderContainer">
{
storeData.map( item => {

return(
<div key={item.store} className="col-lg-3 col-md-3 col-sm-6 cardContainer">
<div className="card">
<div className="card-block">
<h3 className="card-title"> { item.store } </h3>
<p className="card-text"> { item.storeName } </p>
<p className="card-text"> Open Date: { item.openDate } </p>
<div className="cardStatus">
Status
<div className="statusCircle circleFill"/>
</div>
<a className="btn btn-outline-secondary viewBtn">View</a>
</div>
</div>
</div>
)
})
}
</div>
)
}


render() {
return(
<div>
<div className="loaderContainer">
<h3 className="loaderTitle">Ready For IT
</h3>
{ this.loadStores() }
</div>


<div className="loaderContainer">
<h3 className="loaderTitle">Under Construction</h3>
{ this.loadStores() }
</div>


<div className="loaderContainer">
<h3 className="loaderTitle">Upcoming Stores</h3>
{ this.loadStores() }
</div>

</div>

)
}
}

function mapStateToProps(state) {
return { data: state.stores }
}

export default connect(mapStateToProps)(StoreLoader)


My Actions Index

import axios from 'axios'

export const SET_STORES = 'SET_STORES'
export const LOAD_STORES = 'LOAD_STORES'



export function setStores(items) {
return {
type: SET_STORES,
items
}
}

export function loadStoresFromServer() {
return function(dispatch) {
const ROOT_URL = 'http://localhost:3001/api/stores'
axios.get(ROOT_URL)
.then( res => {
//console.log(res.data)
dispatch(setStores(res.data))
})
}
}


My Reducers Index

import { combineReducers } from 'redux'
import { SET_STORES, LOAD_STORES } from '../actions'


const rootReducer = combineReducers({
stores
})


function stores(state = [], action) {
switch(action.type) {
case SET_STORES:
return action.items
case LOAD_STORES:
return {...state, data: action.items }
default:
return state
}
}

export default rootReducer

Answer Source

In your rootReducer your action case

case SET_STORES:
    return action.items

Does not set anything on top of the state. It is returning your action's data, but it is not adding to the redux state tree.

You will need that SET_STORE case to function like this

case SET_STORES:
    return Object.assign({}, state, {
        items: action.items
    })