繁体   English   中英

当商店状态改变时,React 组件不会更新

[英]React component not updating when store state has changed

下面是我的组件类。 该组件似乎永远不会执行 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)

这是地图减速器:

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
  }
}

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

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

数据通过 reducer 中处理操作的结果在 store 中设置/更新/删除。 Reducers 接收应用程序切片的当前状态,并期望获得新状态。 您的组件可能不会重新渲染的最常见原因之一是您正在修改减速器中的现有状态,而不是返回带有必要更改的新状态副本(请查看故障排除部分)。 当您直接改变现有状态时,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]

我希望这会帮助你

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

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

case FETCH_NEW_POSTS
    let posts = state.posts;
    posts.push(action.payload.posts);
    return {
        ...state, 
        posts
    };

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

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
    };

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

componentWillUpdate接收传入的 props作为参数 这时候this.props还是旧的 props。 尝试像这样改变你的方法:

void componentWillUpdate(nextProps, nextState) {
    L.geoJson(nextProps.data).addTo(this.map);
}

另外,使用组件的构造函数时要小心。 那是我的问题。

例如

class extends Component {
   private elementState: ElementState // BAD idea!!

   constructor(props: any) {
      super(props)
      elementState = stateFromReduxStore // BAD idea!!!
   }

   render() {
      return <SomeElement state={elementState} /> // will not be updated!!!
   }
}

如果您通过地图文件将道具传递给您的组件,请确保您正在收听地图文件中的存储。

export const listenToStores = [CommonStore, store];
@connection(maps.listenToStores, maps.getStateFromStores)

建立在玛丽娜回答的基础上

var tempArray = imageArrayState
tempArray.push(5)
setImageArray(tempArray)

var tempArray = []
imageArrayState.foreach(value => {tempArray.push(value)})
tempArray.push(5)
setImageArray(tempArray)

让我的应用程序刷新

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM