【问题标题】:React Lifecycle ( componentDidMount ) with Redux使用 Redux 反应生命周期 (componentDidMount)
【发布时间】:2019-01-02 17:40:38
【问题描述】:

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

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

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

这是一个在 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);

【问题讨论】:

  • 你能发布例子吗?最好谈谈具体情况。
  • componentDidMount 在生命周期中只被调用一次。如果您想在 Redux 更改后获取值,您需要使用 componentDidUpdate

标签: reactjs redux react-redux


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-14
      • 1970-01-01
      • 1970-01-01
      • 2018-10-25
      • 1970-01-01
      • 2019-10-08
      • 2017-02-11
      • 2017-01-06
      相关资源
      最近更新 更多