Xeperis Xeperis - 18 days ago 6
React JSX Question

Redux: re-rendering children on store state update

I have started to learn

react
+
redux
recently. Prior to that I have not had experience with this sort of stack.
So I ran into a problem where I do not understand why child components do not get re-rendered when reducer returns new state.
Full code on GITHUB

This is my parent component source on git:

import React from "react"
import {connect} from "react-redux"

import {fetchWarehouses} from "../../actions/warehouseActions"

import WarehouseMenu from "./WarehouseMenu"
import WarehouseView from "./WarehouseView"
import WarehouseEdit from "./WarehouseEdit"

@connect((store) => {
return {
warehouses: store.warehouses.warehouses,
selectedWarehouse: store.warehouses.selectedWarehouse,
isSelected: store.warehouses.isSelected,
warehouseCount: store.warehouses.warehouseCount,
}
})
export default class WarehousePage extends React.Component {

componentWillMount() {
this.props.dispatch(fetchWarehouses())
}

render() {
return (
<div className="container-fluid">
<div className="row">
<div className="col-sm-2">
Warehouses ({this.props.warehouseCount}):
</div>
<div className="col-sm-10">
<WarehouseMenu warehouseList={this.props.warehouses} />
</div>
</div>
<div className="col-lg-12">
<WarehouseView test={this.props.isSelected} selectedWarehouse={this.props.selectedWarehouse} />
</div>
<div className="col-lg-12">
<WarehouseEdit />
</div>
</div>
)
}

}


And these are children source on git:

import React from "react"
import store from "../../store"
import {fetchOne} from "../../actions/warehouseActions"

export default class WarehouseMenu extends React.Component {

constructor(props) {
super(props)
}

select(id) {
store.dispatch(fetchOne(id))
}

render() {
const {warehouseList} = this.props.warehouseList

if (!warehouseList) {
return <button className="btn btn-success" key="new_warehouse">+</button>
}

const mappedWarehouses = warehouseList.map(wh => <button onClick={this.select.bind(this, wh.id)} className="btn btn-default" key={wh.id}>{wh.name}</button>)
mappedWarehouses.push(<button className="btn btn-success" key="new_warehouse">+</button>)
return (
<div className="btn-group">
{mappedWarehouses}
</div>
)
}


}

And source on git:

import React from "react"
import store from "../../store"
import {deleteWarehouse, fetchWarehouses} from "../../actions/warehouseActions"

export default class WarehouseView extends React.Component {

constructor(props) {
super(props)
}

render() {
const {test, selectedWarehouse} = this.props

if (!test) {
return null
}

return (
<div className="container-fluid">
<div className="row">
<div className="col-sm-2">
ID
</div>
<div className="col-sm-10">
{selectedWarehouse.id}
</div>
</div>
<div className="row">
<div className="col-sm-2">
Name
</div>
<div className="col-sm-10">
{selectedWarehouse.name}
</div>
</div>
<div className="row">
<div className="col-sm-12">
<button className="btn btn-warning">EDIT</button>
<button onClick={this.deleteWarehouse.bind(this, selectedWarehouse.id)} className="btn btn-danger">DELETE</button>
</div>
</div>
</div>
)
}

deleteWarehouse(id) {
store.dispatch(deleteWarehouse(id))
}

}


So whenever I dispatch
deleteWarehouse
I want
WarehouseMenu
to rerender since the state of
store.warehouses.warehouses
changes. I do not get the expected result. Only
WarehousePage
rerenders (e.g.
store.warehouses.warehouseCount
). I've tried
@connect
int store to child components but did not seem to get the desired result also.

Answer

You are not alterning the warehouses property inside your warehouseReducers.js when a DELETE_WAREHOUSE_FULFILLED action is dispatched, but you do alter the warehouseCount

Comments