【问题标题】:React/Redux: Wait for reducer to get propsReact/Redux:等待 reducer 获取 props
【发布时间】:2019-08-01 18:08:45
【问题描述】:

我有以下用于导航的组件:

import React, { Component } from "react";
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';

class TabBar extends Component {
  constructor(props) {
    super(props);

    const noTankAvailable = this.props.tank.tankData.noAssignedTank;
    console.log("noTankAvailable", noTankAvailable);

    if (noTankAvailable === true || noTankAvailable === undefined) {
      this.tabs = [
        { label: "Registration", icon: faSimCard, url: "registration" }
      ];
    } else {
      this.tabs = [
        { label: "Status", icon: faChartBar, url: "status" },
        { label: "History", icon: faHistory, url: "history" },
        { label: "Properties", icon: faSlidersH, url: "properties" }
      ];
    }
    ...
  }
  ...
  render() {
    const { location, match } = this.props;
    const { pathname } = location;
    return (
      <div>
        <Tabs
          className="tabBar"
          contentContainerStyle={tabBarStyles.content}
          inkBarStyle={tabBarStyles.ink}
          tabItemContainerStyle={tabBarStyles.tabs}
          value={pathname}
        >
          {this.renderTabs(match)}
        </Tabs>
      </div>
    );
  }
}

const mapStateToProps = state => ({
  ...state
});

export default connect(mapStateToProps)(TabBar);

这是我的 redux reducer:

import {
  TANK_REQUEST,
  TANK_FAILURE,
  TANK_SUCCESS,
} from '../actions/tankActions';

const testState = {
  isLoading: false,
  currentTank: "",
  tankData: {}
};

export default (state = testState, action) => {
  switch (action.type) {
    case TANK_REQUEST:
      return Object.assign({}, state, { isLoading: true });
    case TANK_SUCCESS:
      if (action.tankData.length > 0) {
        const currentTank = action.tankData[0];
        const tankData = Object.assign({}, state.tankData, { [currentTank._id]: currentTank, isLoading: false });
        return Object.assign({}, state, { currentTank: currentTank._id, tankData });
      } else {
        const tankData = Object.assign({}, state.tankData, { noAssignedTank: true });
        return Object.assign({}, state, { tankData });
      }
    case TANK_FAILURE:
      return Object.assign({}, state, { currentTank: action.id, isLoading: false, error: action.err });
    default:
      return state
  }
}

给出以下场景:当用户登录时,它会获取一个 API 来获取(水)箱。如果用户没有指定的坦克,应用程序应该重定向到注册视图并且导航应该只显示“注册”。

所以我通过一个动作来获取。在我的减速器中,我检查是否有数据,如果没有,我会将noAssignedTank: true 添加到我的状态。我现在想检查一下我的 TabBar 组件是否正确,并根据它隐藏/显示导航链接。

我的问题是我需要等到TANK_FETCHING_SUCCESS 减速器解决后检查noAssignedTank 是否为真。

你可以看到第一个控制台输出是我的console.log("noTankAvailable", noTankAvailable);。所以我的 if/else 语句不起作用,因为起初它是undefined,然后才获得值。

【问题讨论】:

    标签: javascript redux react-redux redux-thunk


    【解决方案1】:

    您必须将this.tabs 设置为组件的状态,并在组件的生命周期方法期间对其进行更新。

    已通过附加测试 (props.tank &amp;&amp; props.tank.tankData) 确保了对 tankData 的检索。

    初始状态在构造函数中使用道具初始化。

    对上一个 tank 的引用也保持在 state (prevTanData) 中,用于比较 props 何时发生变化(当 store 中的异步值将被更新时,redux 将通知连接的组件,然后调用 getDerivedStateFromProps )。

    如果 prevTankDatanextProps.tank.tankData 相同,则返回 null 以告诉 React 状态不需要更改。

    请注意,对于 React componentWillReceiveProps 而不是静态的 getDerivedStateFromProps

        class TabBar extends Component {
            constructor(props) {
                super(props);
                this.state = {
                   tabs: TabBar.computeTabsFromProps(props),
                   prevTankData: props.tank && props.tank.tankData,
                };
            };
    
            static computeTabsFromProps(props) {
                const noTankAvailable = props.tank &&
                                        props.tank.tankData &&
                                        props.tank.tankData.noAssignedTank;
                console.log("noTankAvailable", noTankAvailable);
    
                if (noTankAvailable === true || noTankAvailable === undefined) {
                    return [
                        {
                            label: "Registration",
                            icon: faSimCard,
                            url: "registration"
                        }
                    ];
                } else {
                    return [
                        { label: "Status", icon: faChartBar, url: "status" },
                        { label: "History", icon: faHistory, url: "history" },
                        { label: "Properties", icon: faSlidersH, url: "properties" }
                    ];
                }
            }
            static getDerivedStateFromProps(nextProps, prevState) {
                if ((nextProps.tank && nextProps.tank.tankData) !== prevState.prevTankData) {
                    return {
                        prevTankData: nextProps.tank && nextProps.tank.tankData,
                        tabs: TabBar.computeTabsFromProps(nextProps),
                    }
                }
                return null;
            }
            render() {
                ...
            }
        }
    

    【讨论】:

    • 非常感谢您的回答和解决方案!我非常感谢您的工作,并且您将其描述得非常详细,因此我可以遵循并理解它。唯一的问题是我在getDerivedStateFromProps 中收到tabs: TabBar.computeTabsFromProps(props) 的错误,他找不到定义的props。我用你的代码更新我的问题!
    • 这是一个错字,应该是 nextProps 而不是 props。我已经更新了答案。
    猜你喜欢
    • 2016-10-17
    • 1970-01-01
    • 1970-01-01
    • 2021-10-28
    • 1970-01-01
    • 2017-06-12
    • 1970-01-01
    • 1970-01-01
    • 2017-10-25
    相关资源
    最近更新 更多