【问题标题】:Child Component Not Getting New Data When Redux Updated By Parent Component父组件更新 Redux 时子组件未获取新数据
【发布时间】:2017-07-31 21:17:00
【问题描述】:

我查看了其他似乎有类似问题的问题,但没有一个被接受的答案能解决我的问题。当 redux 使用新 ID 更新时,我正在尝试获取新名称并将它们加载到子组件中。

当我只使用 redux 而没有 state(我更喜欢)时,新 ID 不会传递给子组件,并且根本不会加载名称

或者,我尝试使用state 作为子组件中的名称(您可以在下面的注释文本中看到)。然而......奇怪的是,每次更改 ID 时,组件都会根据之前的 ID 而不是当前的 ID 加载名称。

Redux

const initialState = {
  objectOfIds: {"someID":"someID", "aDifferentID":"aDifferentID"},  // I know this format may seem redundant and odd, but I have to keep it this way
  arrayOfNames: ["John Doe", "Jenny Smith"]
}

父组件

// React
import React from 'react';
import firebase from 'firebase';

//  Components
import ListOfNames from './ListOfNames';

//  Redux
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {set} from './../actions/index.js';

class ParentComponent extends React.Component {
  constructor(props) {
    super(props);
    this.changeIDs = this.changeIDs.bind(this);
  }

  changeIDs() {
    this.props.set("objectOfIds",{"aNewID":"aNewID","someOtherID":"someOtherID","anotherID":"anotherID"});
  }

  render (
    return (
      <div>
        <h2>Parent Component</h2>
        <button onClick={this.changeIDs}>Change Data</button>
        <ListOfNames objectOfIds={this.props.reduxData.objectOfIds}/>
      </div>
    )

  )
}

function mapStateToProps(state) {
    return {
        reduxData: state.reduxData
    };
}

function matchDispatchToProps(dispatch) {
    return bindActionCreators({
      set: set
    }, dispatch)
}

export default connect(mapStateToProps, matchDispatchToProps)(ParentComponent);

子组件

// React
import React from 'react';
import firebase from 'firebase';

//  Redux
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {set} from './../actions/index.js';

// Firebase Database
var databaseRef;

class ListOfNames extends React.Component {
  constructor(props) {
    super(props);
    this.state= {
      arrayOfNames: []
    }
    this.fetchNamesForIds = this.fetchNamesForIds.bind(this);
    this.add = this.add.bind(this);
  }

  componentDidMount() {
    console.log("componentDidMount triggering...");
    firebase.auth().onAuthStateChanged(function (user) {
      if (!user) {
        console.log("no user authenticated");
      }
      databaseRef = firebase.database().ref('/people/' + user.uid);
      this.fetchNamesForIds(this.props.reduxData.objectOfIds);
    })
  }

  // I have tried making the fetch in componentWillReceiveProps so that the function would run anytime the IDs were updated in redux, but "this.props.objectOfIds" and "this.props.reduxData.objectOfIds"
  componentWillReceiveProps() {
    console.log("componentWillReceiveProps triggering...");
    console.log("this.props.objectOfIds");
    console.log(this.props.objectOfIds);
    console.log("this.props.reduxData.objectOfIds");
    console.log(this.props.reduxData.objectOfIds);
    this.fetchNamesForIds(this.props.reduxData.objectOfIds);
    // Note: I have also tried: this.fetchNamesForIds(this.props.objectOfIds); so that the data is passed in from the parent
  }

  // fetched the names for the associated IDs
  fetchNamesForIds(personIds) {
    if (personIds === [] || personIds === undefined || personIds === null) {

上一行的替代

我更愿意将数据存储在 redux 中,以便其他组件可以访问它,但这样做确实允许加载数据,但它加载时有延迟(即,当我更改 ID 时,它会加载关联的名称到以前的 ID)

      // this.setState({
      //   arrayOfNames: []
      // });
      this.props.set("arrayOfNames", []);
      return
    }
    var arrayOfNames = [];
    // loop through person and set each value into the arrayOfNames array
    Object.keys(IDs).map(function(person, index) {
      console.log("person = " + person);
      console.log("index = " + index);
      // get names associated with the ids obtained
      var name = ''
      databaseRef.child('people').child(person).limitToFirst(1).on("value", function(snapshot) {
        var firstName = snapshot.child('firstName').val()
        var lastName = snapshot.child('firstName').val()
        name = firstName + " " + lastName
        console.log("name = " + name);
        arrayOfNames.push(name);
        console.log("arrayOfNames = " + arrayOfNames);
        this.props.set("arrayOfNames", arrayOfNames);

上一行的替代

我更愿意将数据存储在 redux 中,以便其他组件可以访问它,但这样做确实允许加载数据,但它加载时有延迟(即,当我更改 ID 时,它会加载关联的名称到以前的 ID)

        // this.setState({
        //   arrayOfNames: arrayOfNames
        // });
      }.bind(this));
    }.bind(this));
  }

  render() {
    return(
      (this.props.user.arrayOfNames === [] || this.props.user.arrayOfNames === undefined || this.props.user.arrayOfNames === null || this.props.user.arrayOfNames.length < 1)
        ? <span>no people selected</span>
        : <div>
            <h5>List of People</h5>
            {this.props.user.arrayOfNames.map((name, index) => {
              return (
                  <h5>{name}</h5>
              )
            })}
          </div>
    )
  }
}

ListOfNames.propsTypes = {
  objectOfIds: React.PropTypes.Object
};


function mapStateToProps(state) {
    return {
        reduxData: state.reduxData
    };
}

function matchDispatchToProps(dispatch) {
    return bindActionCreators({
      set: set
    }, dispatch)
}

export default connect(mapStateToProps, matchDispatchToProps)(ListOfNames);

类似问题:

有谁知道我如何让我的组件根据 redux 中的当前 ID 加载数据?

【问题讨论】:

  • 对你的父组件有点困惑。如果你在渲染中放一个console.log(this.props.user),你会看到什么?看起来您将 reduxData 作为道具传递给您的父组件,但您只调用 this.props.user,我不确定它如何在不破坏 reduxData 看起来像的情况下访问它
  • 这是问题中的错字。我更新了问题中的 ParentComponent。现在应该更有意义了

标签: javascript reactjs firebase-realtime-database redux web-component


【解决方案1】:

可能是因为对象键已更改,但对象引用未更改。 一个 hacky 解决方案是调用 this.forceUpdate() 在更改后更新组件:)

【讨论】:

    【解决方案2】:

    我有一个类似的问题,我在一个页面上多次加载子组件,尽管传入了我认为是唯一 ID 的内容,但它只会引用第一个 ID。我知道这并不完全是您所遇到的情况,但这将允许您拥有一个唯一的对象键和一个唯一的对象引用,这有望解决您的问题。

    这是我为此使用的包:https://www.npmjs.com/package/react-html-id。当你导入包时,你需要有大括号。

    import { enableUniqueIds } from 'react-html-id'
    

    其余的在 npm 上解释。

    【讨论】:

      【解决方案3】:

      提示:如果使用新的 javascript 语法,则无需绑定函数。

      this.add = this.add.bind(this); 将通过编写 add 方法来解决,例如:

      add = () => {
      };
      

      【讨论】:

      • 这仍然返回Syntax error: Unexpected token(在add之后直接指示=
      【解决方案4】:

      问题是子组件组件WillReceiveProps。您没有使用传播到该组件的新道具。使用 nextProps 调用 componentWillReceiveProps,其中包含更新后的 props。

      在您的子组件中使用它

      componentWillReceiveProps(nextProps) {
          console.log("componentWillReceiveProps triggering...");
          console.log("nextProps.objectOfIds ", nextProps.objectOfIds);
          console.log("nextProps.reduxData.objectOfIds ", nextProps.reduxData.objectOfIds);
          this.fetchNamesForIds(nextProps.reduxData.objectOfIds);
      }
      

      【讨论】:

        猜你喜欢
        • 2019-02-17
        • 1970-01-01
        • 1970-01-01
        • 2021-10-30
        • 2022-01-13
        • 1970-01-01
        • 2017-04-17
        • 2018-11-18
        • 1970-01-01
        相关资源
        最近更新 更多