存储状态更改时,React组件不会更新

Jac*_*son 9 javascript state reactjs redux

下面是我的组件类.该组件似乎永远不会执行componentWillUpdate(),即使我可以通过在mapStateToProps中返回之前的日志记录来查看状态更新.状态是100%更改,但组件不刷新.

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)
Run Code Online (Sandbox Code Playgroud)

这是地图缩减器:

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
  }
}
Run Code Online (Sandbox Code Playgroud)

经过一番更多的测试和记录看来,当它进入状态映射到的道具,它使用映射到道具的状态对象包含正确的数据,所以state.map.data是正确的,我可以看到从返回的获取.但是当我在componentWillUpdate()中记录this.props时,数据对象就在那里但是为空.

Nat*_*anL 26

因为你没有改变引用,所以 React 的浅比较不会检测到更新。

我将在博客文章中使用一个简单的示例。在您的减速器中,您可能正在执行以下操作:

case FETCH_NEW_POSTS
    let posts = state.posts;
    posts.push(action.payload.posts);
    return {
        ...state, 
        posts
    };
Run Code Online (Sandbox Code Playgroud)

取而代之的是,您必须执行以下操作:

case FETCH_NEW_POSTS
    let posts = [...state.posts]; // we're destructuring `state.posts` inside of array, essentially assigning the elements to a new array.
    posts.push(action.payload.posts);
    return {
        ...state, 
        posts
    };
Run Code Online (Sandbox Code Playgroud)

根据您的用例 Object.assign() 或 lodash 的 clone/deepclone 可能更惯用。


Mar*_*ina 9

我有一个类似的问题,在阅读以下内容后我找到了答案:

通过reducer中处理操作的结果,可以在存储中设置/更新/删除数据。Reducer会收到您应用程序切片的当前状态,并希望重新获得新状态。可能不重新渲染组件的最常见原因之一是,您正在修改化简器中的现有状态,而不是返回具有必要更改的新状态副本(请参阅“疑难解答”部分)。当您直接更改现有状态时,Redux不会检测到状态差异,也不会通知组件存储已更改。因此,我肯定会检查您的化径器,并确保您不改变现有状态。希望有帮助!(https://github.com/reactjs/redux/issues/585

当我尝试Object.assign({}, object)像您一样使用时,它还是无法正常工作。所以当我发现这个:

Object.assign仅制作浅表副本。(https://scotch.io/bar-talk/copying-objects-in-javascript

然后我知道我必须这样做: JSON.parse(JSON.stringify(object))

或者只是这样: {...object}

对于数组: [...theArray]

希望对您有帮助


Bra*_*don 8

componentWillUpdate接收传入的props 作为参数.这时,this.props仍然是老道具.尝试更改您的方法,如下所示:

void componentWillUpdate(nextProps, nextState) {
    L.geoJson(nextProps.data).addTo(this.map);
}
Run Code Online (Sandbox Code Playgroud)