Below is my component class. The component never seems to execute componentWillUpdate(), even when I can see the state updating by logging before the return in mapStateToProps. The state is 100% changing, however the component doesn't refresh.
import React, { Component } from 'react' import { connect } from 'react-redux' import { search } from './mapActions' import L from 'leaflet' class Map extends Component { componentDidMount() { L.Icon.Default.imagePath = './images' this.map = new L.Map('map', { center: new L.LatLng(this.props.lat, this.props.lng), zoom: this.props.zoom, layers: L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { attribution: '<a href="http://osm.org/copyright">OpenStreetMap</a> contributors' }) }) } componentWillUpdate() { console.log('UPDATE MAP') L.geoJson(this.props.data).addTo(this.map) } render() { return <div id="map"></div> } } const mapStateToProps = (state) => { return { isFetching: state.isFetching, data: state.data } } const mapDispatchToProps = (dispatch) => { return { search: (name) => { dispatch(search(name)) } } } export default connect( mapStateToProps, mapDispatchToProps )(Map)
And here is the map reducer:
const initialState = { isFetching: false, data: {} } export const map = (state = initialState, action) => { switch(action.type) { case 'REQUEST_SEARCH_RESULTS': return Object.assign({}, state, { isFetching: true }) case 'RECEIVE_SEARCH_RESULTS': return Object.assign({}, state, { isFetching: false, data: action.data }) default: return state } }
After some more testing and logging it seems that when it goes to map state to props the state object it uses to map to props contains the correct data, so state.map.data is correct and I can see the return from the fetch. However when I then log this.props in componentWillUpdate(), the data object is there but empty.
State updates in React are asynchronous; when an update is requested, there is no guarantee that the updates will be made immediately. The updater functions enqueue changes to the component state, but React may delay the changes, updating several components in a single pass.
There are two common reasons why React might not update a component even though its props have changed: The props weren't updated correctly via setState. The reference to the prop stayed the same.
React components automatically re-render whenever there is a change in their state or props. A simple update of the state, from anywhere in the code, causes all the User Interface (UI) elements to be re-rendered automatically.
Forcing an update on a React class component In any user or system event, you can call the method this. forceUpdate() , which will cause render() to be called on the component, skipping shouldComponentUpdate() , and thus, forcing React to re-evaluate the Virtual DOM and DOM state.
I had a similar problem and I found out the answer after read this:
Data gets set/updated/deleted in the store via the results of handling actions in reducers. Reducers receive the current state of a slice of your app, and expect to get new state back. One of the most common reasons that your components might not be re-rendering is that you're modifying the existing state in your reducer instead of returning a new copy of state with the necessary changes (check out the Troubleshooting section). When you mutate the existing state directly, Redux doesn't detect a difference in state and won't notify your components that the store has changed. So I'd definitely check out your reducers and make sure you're not mutating existing state. Hope that helps! (https://github.com/reactjs/redux/issues/585)
When I tried use Object.assign({}, object)
as you, it didn't work anyway. So was when I found this:
Object.assign only makes shallow copies. (https://scotch.io/bar-talk/copying-objects-in-javascript)
Then I understood that I had to do this: JSON.parse(JSON.stringify(object))
or just this: {...object}
For Arrays: [...theArray]
I hope that this will help you
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With