【问题标题】:Correct way to pass Redux store state to child components in ReactJS在 ReactJS 中将 Redux 存储状态传递给子组件的正确方法
【发布时间】:2019-06-27 18:41:18
【问题描述】:

==已编辑问题,因为不幸的是解决方案不起作用!==

==我现在意识到这是因为我的 Redux Store 没有正确更新!==

我正在尝试使用 Redux 在 ReactJS 中构建一个项目,该项目有一个 Redux 存储,并通过 Axios 获取定期更新状态。

此 Axios fetch 更新初始存储状态正常。

我将商店状态作为道具传递给父级的子元素。

当 store 状态改变时,如果 Child 受到影响,我需要 props 向下传递并重新渲染 Child。

我曾想过,如果我将道具(由 mapStateToProps 设置)发送给 Child,并且状态发生了变化,这会重新发送道具并导致重新渲染,但事实并非如此。

任何有关实现我正在尝试的正确方法的建议将不胜感激。

我已经通过控制台记录了来自 Parent 元素的 componentDidMount 方法的道具,并且我看到了道具更新,正如我所期望的那样;每次我手动更改获取的 JSON 时,都会更改道具以反映这一点。

父元素:

class Parent extends React.Component {

    componentDidMount() {
        this.props.updatePanels();
        console.log(this.props);
        this.interval = setInterval(() => {
        this.props.updatePanels();
        }, 5000);
       }

     componentWillUnmount() {
       clearInterval(this.interval)
     }

     renderList() {
        return this.props.panels.map((panel) => {
          return (
              <Child key={panel.id} lat={panel.lat} lng={panel.lng} />
          );
        });
      }

    render() {
        return (
            <div>
                {this.renderList()}
            </div>

        );
    }
}

子元素:

const Child = props => (
    <div key={props.id}>
         <div>{props.lat}</div>
         <div>{props.lng}</div>
    </div>
)

Redux Action Creator

import panelFetch from '../dataCalls/panelFetch';

export const updatePanels = () => {

    return async (dispatch) => {
      const response = await panelFetch.get("/panelList.json");

      console.log(response.data);

      dispatch ({
        type: 'UPDATE_PANELS',
        payload: response.data
      });
    };
  };

Redux 更新面板缩减器

export default (state = [], action) => {

    switch (action.type) {
      case 'UPDATE_PANELS':
        return action.payload;
      default:
        return state;
    }

  };

Redux 减速器

import { combineReducers } from 'redux';
import updatePanelsReducer from './updatePanelsReducer'; //compartmentalise our reducer

const panelReducer = () => {
    return [{
        "id": 400016,
        "lat": 51.509865,
        "lng": -0.118092
    }, {
        "id": 400017,
        "lat": 51.509865,
        "lng": -0.118092
    }, {
        "id": 400018,
        "lat": 51.509865,
        "lng": -0.118092
    }, {
        "id": 400019,
        "lat": 51.509865,
        "lng": -0.118092
    }
];
};

export default combineReducers({
    panels: panelReducer,
    updatePanels: updatePanelsReducer
  });

【问题讨论】:

    标签: reactjs redux


    【解决方案1】:

    子组件不应将其道具置于其状态。

    子组件没有更新,因为它的渲染方法不依赖于它的 props,而是依赖于它自己的内部状态,你在它的构造函数中设置了一次并且永远不会改变。

    如果您的子组件如下所示,它将起作用:

    class Child extends React.Component {
        constructor(props) {
            super(props)
        }
    
        render() {
            return (
                <div key={this.props.id}>
                     <div>{this.props.lat}</div>
                    <div>{this.props.lng}</div>
                </div>
            )
        }
    }
    

    此外,您可能需要考虑摆脱类组件的所有样板,尤其是如果您只使用它的渲染方法。您可以将其重写为函数组件,如下所示:

    const Child = props => (
        <div key={props.id}>
             <div>{props.lat}</div>
             <div>{props.lng}</div>
        </div>
    )
    

    【讨论】:

    • 尤其是关于重写组件的部分。
    • 不幸的是,对此并不满意。我已经将 Child 重构为上面的功能组件,并且发生了同样的问题。这可能与我的 mapStateToProps 有关吗? const mapStateToProps = (state) =&gt; { return { panels: state.panels } }; export default connect (mapStateToProps, { updatePanels: updatePanels })(Parent); 奇怪的是,我在记录道具时看到控制台的输出是正确的
    【解决方案2】:

    问题是您最初在构造函数中只设置了一次Child 组件的状态。 props 的后续更改不会更新 Child 组件的状态。

    你可以使用 React 的 getDerivedStateFromProps(props, state) 方法设置初始状态,然后在 props 更新后更新状态。在这里阅读 https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops

    您可以简单地将 props 传递给 Child 组件,而无需设置状态。

    class Child extends React.Component {
        constructor(props) {
            super(props)
        }
    
        render() {
            return (
                <div key={this.props.id}>
                     <div>{this.props.lat}</div>
                    <div>{this.props.lng}</div>
                </div>
            )
        }
    }
    

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-03
      • 1970-01-01
      • 1970-01-01
      • 2017-01-26
      • 1970-01-01
      • 2021-04-17
      • 2016-08-31
      • 2019-01-20
      相关资源
      最近更新 更多