Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React component not updating when store state has changed

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.

like image 403
Jacob Mason Avatar asked Mar 10 '16 12:03

Jacob Mason


People also ask

Why is React not updating on state change?

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.

Why isn't my React component updating?

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.

Does React component Rerender when state changes?

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.

How do I force a state update React?

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.


1 Answers

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

like image 138
Marina Avatar answered Oct 08 '22 20:10

Marina