使用Redux反应生命周期(componentDidMount)

时间:2018-07-25 19:56:53

标签: reactjs redux react-redux

我对React生命周期有些困惑,特别是 componentDidMount 与redux交互的方式。

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

我环顾四周,但有些答案像 Why is componentDidMount not being called when I re-render?ComponentDidMount called multiple times使我感到困惑。

下面是一个示例,当道具更改时,代码无法正确更新

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);

2 个答案:

答案 0 :(得分:2)

当Redux获取新数据时,它通过向下连接到所有连接的组件触发道具更改。根据商店的变化,组件的行为可能有一些可能性:

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

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

    发生这种情况时,该组件将不会调用componentDidMount

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

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

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

答案 1 :(得分:1)

React使用Reconciliation来确定何时应卸载组件然后重新安装。 React会进行差异检查,以确定何时更新组件及其所有子组件。在父级上没有任何更改时,它不会重新安装任何组件,因此,如果仅更改了组件子级的某些方面,则不会再次调用componentDidMount。因此,如果您提供了返回新组件组的另一种可能性,例如,如果异步获取状态时返回了活动指示器,那么每次重新安装不同的组件组时,您都会得到componentDidMount调用。