繁体   English   中英

React Redux:连接的子组件未接收道具

[英]React Redux: Connected child component not receiving props

我似乎无法弄清楚问题是什么。 我有一个名为DisplayItems的组件,该组件从API(项目列表)中获取一些数据。

我正在使用Redux操作和thunk中间件从API获取项目和数据。 我将项目和其他数据作为对象数组保存到redux存储,并将其命名为entriesData 实际的数组位于entriesData.data 我正在使用connect将状态和动作连接到DisplayItems的道具。

接下来,我有一个名为GalleryItemContentV1的子组件。 GalleryItemContentV1未连接到GalleryItemContentV1 它只是从DisplayItems接收数据, DisplayItems遍历项目数组并将每个项目传递给GalleryItemContentV1 因此,再次, DisplayItems遍历this.props.entriesData.data并将每个项目作为名为entry的道具传递给GalleryItemContentV1

最后,我在GalleryItemContentV1有一个名为TestCom的子组件。 这就是问题所在。 我还将从DisplyItem获得的项目传递给TestCom 因此,数据流为DisplayItems (已连接)> GalleryItemContentV1 (未连接)> TestCom (已连接)。

TestCom已连接到redux。 它使用redux中的一些操作来更新entriesData.data的项目。 当我在TestCom更新this.props.entriesData.dataTestCom GalleryItemContentV1接收更新的数据,但是TestCom却什么也没收到。 TestCom的项目永远不会更新。

我发现问题是当我将TestCom连接到redux时。 如果TestCom没有连接到redux,它也会收到更新的GalleryItemContentV1 ,就像GalleryItemContentV1一样。

组件如下。 我试图尽可能简化它们。

DisplayItems

import React, {Component} from 'react';
import GalleryItemContentV1 from './GalleryItemContentV1';
import { connect } from 'react-redux';
import {getContestEntriesPageData} from '../../actions/contest';

class DisplayItems extends Component {
  componentDidMount(){
    this.props.getContestEntriesPageData(uri, search);
  }

  render(){

    console.log('DisplayItems props', this.props);

      return (
        <div>
          <div className="card-deck thumbnails" id="card-list">
            {  this.props.entriesData.data instanceof Array ? 
                  this.props.entriesData.data.map(function(object, i){
                    return <GalleryItemContentV1 
                      entry={object} key={i} 
                      arr_key={i}
                    />;
                  }, this) : ''
              }
          </div>
        </div>
      )
  }
}

const mapStateToProps = state => (
  {
    entriesData: state.entriesData,
  }
)

const mapDispatchToProps = (dispatch) => {
  return {
    getContestEntriesPageData: (uri, search) => {
      dispatch(getContestEntriesPageData(uri, search));
    }
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(DisplayItems);

GalleryItemContentV1

import React, { Component } from 'react';
import TestCom from './TestCom';

class GalleryItemContentV1 extends Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
        <div>
        <TestCom entry={this.props.entry} />
      </div>
    );
    }
}
export default GalleryItemContentV1;

德讯通

我正在this.props.entry.VotesCount输出this.props.entry.VotesCount (来自DisplayItems的项目)的TestCom 这就是问题所在。 出于某种原因,当我将TestCom连接到redux时,它的道具不会更新,但是当它与Redux断开连接时,它的道具就会被更新。

import React, {Component} from 'react';
import { connect } from 'react-redux';

class TestCom extends Component {
  constructor(props) { 
    super(props);
  }

  render(){

    console.log('TestCom props', this.props);

    return (

      <div>{this.props.entry.VotesCount}</div>

    )
  }
}

const mapStateToProps = state => (
  {
    user: state.user
  }
)
export default connect(mapStateToProps)(TestCom);

这是我在配置redux的地方,但是我不认为知道相关的东西,因为GalleryItemContentV1看到的更新数据很好。

import {createStore, applyMiddleware} from 'redux';
import thunk from 'redux-thunk';
import ContestReducer from '../reducers/contest';

export default function configureStore(initialState) {
  return createStore(
    ContestReducer,
    initialState,
    applyMiddleware(thunk)
  );
}

因此,总结一下。

DisplayItems (已连接,可以从存储中接收更新的数据)> GalleryItemContentV1 (未连接,可以接收更新)> TestCom (已连接,不接收更新,但如果断开则接收更新)

这是我的减速机,以防万一。

import * as ContestActionTypes from '../actiontypes/contest';

const initialState = {
  contest: null,
  subscriptions: [],
  user: null,
  page: null
}
export default function Contest(state=initialState, action) {
  console.log('redux action reducer: ', action)
  switch(action.type) {
    case ContestActionTypes.HANDLE_VOTE:
      const newState = { ...state };
      if (newState.entriesData) {
        const index = newState.entriesData.data.findIndex(x => x.id === action.entry.id)
        newState.entriesData.data[index].VotesCount = action.vote;
      } else {
        newState.entry.VotesCount = action.vote;
      }

      return newState

      default:
        return state;
  }
}

我还注意到GalleryItemContentV1发生了同样的事情。 如果我连接了它,那么它将停止从DisplayItems / redux存储接收更新。

任何输入表示赞赏。 谢谢!

您正在改变状态。 您正在该Slice Reducer中复制顶层状态的浅层副本,但并未在其中复制所有嵌套层的副本。 然后,您连接的组件正在提取state.entriesData ,该引用未更改。 因此, connect wrapper组件认为状态根本没有改变,因此不会重新呈现您自己的组件。

“不可修改的更新模式”上Redux文档页面特别指出了这一点,这是一个常见错误。

如果一成不变地更新嵌套状态太麻烦了,我建议您研究immer不变式更新库 另外,我们新的redux-starter-kit软件包内部使用Immer来编写更简单的reducer。

另外,请参阅我的文章惯用的Redux:React-Redux的历史和实现,以获取有关背景以及内部connect工作方式的详细信息。

是的,我也认为您正在改变自己的状态。 以下是reducer的TOGGLE_TODO案例。 我希望此代码段适用于您的代码。

  case TOGGLE_TODO:
  return Object.assign({}, state, {
    todos: state.todos.map((todo, index) => {
      if (index === action.index) {
        return Object.assign({}, todo, {
          completed: !todo.completed
        })
      }
      return todo
    })
  })

因此,在您的情况下,如果id匹配,则update是使用action.vote 另请阅读有关深层和浅层对象副本的信息。

markerikson是正确的,但是我在这里发布了对我有帮助的具体答案。

问题是我尝试使用普通方法Object.assign({},state,{})来更新对象内部的数组(entriesData为对象,entriesData.data为数组)时,一直在使用JSON.parse(JSON.stringify(state))。 我必须阅读Mozilla的解释( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign )以了解发生了什么。 我之前看过JSON.parse解决方案,但是我并不真正理解浅层和深层克隆,而且,无论浅层克隆是什么,我都不认为我有罪。 原来,我是。

这是我更新的减速器,效果很好。

case ContestActionTypes.HANDLE_VOTE:
  const newState = JSON.parse(JSON.stringify(state));
  if (newState.entriesData) {
    const index = newState.entriesData.data.findIndex(x => x.id === action.entry.id)
    newState.entriesData.data[index].VotesCount = action.vote;
  } else {
    newState.entry.VotesCount = action.vote;
  }

  return newState;

暂无
暂无

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

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