首页 > 解决方案 > 使用 Redux 反应生命周期 (componentDidMount)

问题描述

我对 React Lifecycle 有点困惑,特别是componentDidMount如何与 redux 交互。

这是场景:我有一个连接到 redux 存储的组件,我不知道是否应该在更新 redux 存储并且连接组件中的 props 更改时再次调用 componentDidMount。现在,每次道具更改时都会重新安装一个组件。但是,我有另一个单独的连接组件,当它的道具改变时不会重新安装。所以现在我因为这种不一致的行为而迷路了。

我环顾四周,但有些答案,例如 为什么我重新渲染时没有调用 componentDidMount?多次调用 ComponentDidMount让我感到困惑。

这是一个在 props 更改时没有正确更新的代码示例

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from "redux";
import PropTypes from 'prop-types';


/* material UI */
import Collapse from '@material-ui/core/Collapse';
import Divider from '@material-ui/core/Divider';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import Tooltip from '@material-ui/core/Tooltip';

/* Icons */
import {Copy,FolderMinus,FolderPlus} from 'react-feather';

/* Our Components */
import { history } from '../../redux/store/index';
import { getClusters, setCluster, toggleClusters } from '../../redux/actions/ClusterActions';


class SideClustersList extends Component{
  constructor(props){
    super(props);
  
  }
  componentDidMount(){
    /* get a list of clusters based on the apiurl */
    console.log("props get clusters")
    console.log(this.props.base_url)
    this.props.getClusters(this.props.base_url);
  }
  setCurrentCluster(cluster) {
    this.props.setCluster(this.props.base_url, cluster)
    // Switch tabs to display selected cluster
    history.push("/clusters")
  }
  render(){
    const { classes,clusters, open } = this.props;
    return (
      <React.Fragment>
        <ListItem button className={classes.nested} onClick={this.handleClick}>
            <Tooltip id="tooltip-bottom" title="Clusters" placement="top">
          <ListItemIcon >
            {open ? <FolderMinus/>:<FolderPlus/>}
          </ListItemIcon>
            </Tooltip>
          <ListItemText primary="Clusters" /></ListItem>
        <Collapse in={open} timeout="auto" unmountOnExit>
          <Divider />
        <List component="div" disablePadding>
        {clusters ? (
          clusters.map(cls =>(
          <ListItem button key={cls.clusterName} component='a'
            /*href={'/clusters/'+this.props.accounts[0]['account_name']+'/'+cls.clusterName}*/
            onClick={() => this.setCurrentCluster(cls.clusterName)}>
            <Tooltip id="tooltip-top" title={cls.clusterName} placement="top">
            <ListItemIcon>
              <Copy />
            </ListItemIcon>
            </Tooltip>
            <ListItemText primary={cls.clusterName} />
      </ListItem>
    ))): null}
      </List>
      </Collapse>
      </React.Fragment>
    )
  }
  handleClick = () => {
    this.props.toggleClusters(!this.props.open)
  };

}
SideClustersList.propTypes = {
  getClusters: PropTypes.func.isRequired
};

const mapStateToProps = state => ({
  account_name: state.accounts.item.account_name,
  base_url: state.accounts.item.apiurl,
  cluster: state.clusters.item,
  clusters: state.clusters.items,
  open: state.clusters.open,
});

function mapDispatchToProps(dispatch) {
  return bindActionCreators({getClusters, setCluster, toggleClusters}, dispatch)
}

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

标签: reactjsreduxreact-redux

解决方案


当 Redux 获得新数据时,它会通过 connect down 到所有连接的组件来触发 props 更改。根据存储更改,组件的行为方式有一些可能性:

  1. 当与 store 的连接不影响组件的父组件时,它将启动常规组件生命周期:

    • static getDerivedStateFromProps()
    • shouldComponentUpdate()
    • render()
    • getSnapshotBeforeUpdate()
    • componentDidUpdate()

    发生这种情况时,组件将不会调用componentDidMount,如您所见。

  2. 当孩子的父母受到影响时,有可能将该组件从dom中移除并重新进入。什么时候可以?例如,当父组件决定提供的道具是新的并且它应该重新渲染其所有子组件时。发生这种情况时,您输入从 dom 中卸载组件并被componentWillUnmount()调用然后使用常规生命周期方法再次安装的路径:

    • constructor()
    • static getDerivedStateFromProps()
    • render()
    • componentDidMount()

您可以在此处阅读有关和解的更多信息:https ://reactjs.org/docs/reconciliation.html


推荐阅读