与Redux动态数据源

时间:2018-06-05 15:17:27

标签: javascript reactjs react-native redux react-redux

我正在使用Udemy: The Complete React Native and Redux Course by Stephen Grider学习RN,而我正在使用Firebase创建一个管理应用。

我有来自react-redux库的连接函数并且有mapStateToProps()所以每当我的状态发生变化时,我都会在组件中将它们作为道具接收。

我创建了一个从Firebase数据库中获取数据的操作,我将在componentWillMount()中调用它,但由于获取数据是异步任务,我必须在{{1}中创建我的数据源}。

但是教练说我必须在componentWillReceiveProps()createDataSource()中拨打我的componentWillMount()

我不明白为什么!!如果我在状态中有任何变化(这是我的员工名单),我将收到它们作为道具,所以我认为仅仅在componentWillReceiveProps()中拨打createDataSource()就足够了。

有人能为我声明吗?是否有任何我忘记处理的特殊情况?

更新

EmployeeActions.js:

componentWillReceiveProps()

EmployeeList.js:

export const employeesFetch = () => {
  const { currentUser } = firebase.auth();

  return dispatch => {
    firebase
      .database()
      .ref(`/users/${currentUser.uid}/employees`)
      .on("value", snapshot => {
        dispatch({ type: EMPLOYEES_FETCH_SUCCESS, payload: snapshot.val() });
      });
  };
};

所以我正在使用 componentWillMount() { this.props.employeesFetch(); this.createDataSource(this.props); } componentWillReceiveProps(nextProps) { this.createDataSource(nextProps); } createDataSource({ employees }) { const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 }); this.dataSource = ds.cloneWithRows(employees); } 来展示我从Firebase获取的员工!如果我在ListView中使用createDataSource(),我会遇到任何问题吗?

2 个答案:

答案 0 :(得分:2)

我还完成了你提到的Udemy课程,首先我要说使用componentWillReceiveProps()和componentWillMount()道具已被弃用,不应再使用了。在新项目中,建议您使用静态getDerivedStateFromProps()和componentDidUpdate()。官方React文档将为您提供有关此主题的其他信息。

但是仅在初始渲染完成后调用componentWillReceiveProps(),因此如果组件在实例化时没有收到道具,则需要在componentWillMount()中进行设置。

修改 如果您想坚持新的最佳实践,那么这将是最佳选择:

  • 在构造函数中进行任何实例化
  • 异步设置需要进入componentDidMount()
  • 静态getDerivedStateFromProps()在每次渲染之前调用(由于更新而初始渲染和重新渲染)
  • 在初始渲染后的道具更新上调用componentDidUpdate()

答案 1 :(得分:1)

我也参加了同样的Udemy课程,并且在我了解到某些React生命周期已被弃用并由其他生命周期替代后,我正在重构代码。

这是我获取和更新的旧逻辑:

    state = { dataSource: [] }

    componentWillMount() {
      const { userCentres } = this.props;

      this.props.fetchCentres(userCentres);
      this.createDataSource(this.props);
    }

    componentWillReceiveProps(nextProps) {
      this.createDataSource(nextProps);
    }

    createDataSource({ centresList }) {
      this.setState({ dataSource: centresList });
    }

我尝试使用static getDerivedStateFromProps替换当前的逻辑,但由于无法在其作用域内使用关键字this导致无法使用this.createDataSource(props),因此遇到了问题。我还读了“ you probably don't need derived state”,之后决定最好改用getSnapshotBeforeUpdatecomponentDidUpdate

  

getSnapshotBeforeUpdate()在最近渲染的输出提交到例如DOM。它使您的组件可以在DOM可能发生更改之前从DOM捕获一些信息(例如,滚动位置)。 此生命周期返回的任何值都将作为参数传递给componentDidUpdate()

这就是我重构代码的方式:

      state = { dataSource: [] }

      componentDidMount() {
        const { userCentres } = this.props;

        this.props.fetchCentres(userCentres);
      }

      componentDidUpdate(prevProps, prevState, snapshot) {
        if (snapshot) {
          this.createDataSource(this.props);
        }
      }

      getSnapshotBeforeUpdate(prevProps) {
        if (prevProps.centresList !== this.props.centresList) {
          return true;
        }

        return null;
      }

      createDataSource({ centresList }) {
        this.setState({ dataSource: centresList });
      }

尽管我不是100%地确定这是解决问题的最佳方法,但最终还是为我工作。我还应该注意,这是一个PureComponent。