ReactJS - 子组件从其父组件调用函数时超出的最大堆栈

时间:2018-01-07 11:45:28

标签: reactjs

我有一个子组件(调用另一个组件),我从其父组件中调用一个函数:

这是子组件中的render方法:

render() {
    ...
        return (
            <secondChild
                getName={(name) => {
                     this.props.(handleName(name))
                  }
               }
            />
   );

在父组件中,我将使用setState:

handleName = (name) => {
    …
    this.setState(….);
 }

父级中的setState导致重新渲染,因此将重新渲染子级。这导致无限循环并最终导致“超出最大堆栈...&#34;

我想知道为什么孩子会在重新渲染后立即调用该函数?我应该更改getName吗? [因为它是一个箭头功能]

如何更改代码以避免此循环?

3 个答案:

答案 0 :(得分:2)

出现此问题可能是因为您在渲染子组件期间尝试更改父组件的state。这将导致无限循环,因为状态更改会导致组件重新渲染,这意味着父级将重新渲染其子级,从而导致它们调用更新父级state的相同方法。

您通常会更改状态以响应某些用户操作,或者从api中获取某些数据后,但在呈现组件时不会。如果您需要从api获取数据并将其设置为您使用componentDidMount的状态,请参阅react docs。像这样:

componentDidMount() {
    // safe to call setState here
    this.setState({ name : 'value' });
}

答案 1 :(得分:1)

您实际上是在生成一个无限循环。虽然我们没有子组件的代码,但如果每次渲染时至少调用一次getName,这将导致问题。

解决问题的一种方法是让子组件无法重新渲染。通过给予它;

shouldComponentUpdate() { return false; }

你可以确保它只被渲染一次。请注意,此函数是可扩展的,并且取决于nextProps和nextState,您可以使它在props更新时不会重新呈现但是当状态执行时,或者跳过重新呈现以进行某些更改而不是其他更改。

例如,以下代码仅在组件的状态更新时才会重新呈现;

shouldComponentUpdate(nextProps, nextState) {
    let stateHasChanged = false;
    Object.keys(nextState).forEach((stateKey) => {
        if (this.state[stateKey] !== nextState[stateKey]) {
            stateHasChanged = true;
        }
    });

    return stateHasChanged;
}

正如评论中所指出的,快速免责声明是您应该尝试尊重React的生命周期而不是在渲染中使用setState。但是,如果您希望这样做,那就是这样。

答案 2 :(得分:1)

在父母中尝试isChildMounted状态,如下所示:

父组件中的

handleName = (name) => {
    if(!this.state.isChildMounted){
        this.setState({
             isChildMounted: true,
             ...
             ...
         });
    }
 }