为什么高阶组件中的componentDidMount会被多次调用?

4

根据文档,描述如下:

在客户端(而非服务器端)仅被调用一次,即在初始渲染完成之后立即执行。

现在,当我尝试创建一个高阶组件时:

import React from 'react';
import { connect } from 'react-redux';

function wrap(Wrapped) {

  class Wrapper extends React.Component {
    componentDidMount() {
      // I will place some reusable functionality here which need to
      // be called once on mounted.
      console.log('wrapper component mounted');
    }
    render() {
      return <Wrapped {...this.props}/>
    }
  }
  return Wrapper;
}

class Wrapped extends React.Component {
  componentDidMount() {
    console.log('wrapped component mounted');
  }
  render() {
    return <div></div>;
  }
}

connect()(wrap(Wrapped));

现在,每当props发生变化时,控制台将打印以下内容:
'wrapped component mounted'
'wrapper component mounted'

如果我移除Wrapper,它只会在第一次挂载时打印一次:
`wrapped component mounted`

所以,为什么高阶组件中的componentDidMount会被调用多次?

connect()(wrap(Wrapped)); <-- 替换为 Wrapped - Kokovin Vladislav
@ffxsam 对不起,如果我没有正确理解您的评论,我的英语不是很好。但是,如果我没有错的话,当这些组件(WrapperWrapped)已经挂载时,只要它没有卸载,componentDidMount将不会再次调用。而我在这里的意思是,只要props更改,这两个componentDidMount总是会被调用。 - Mas Bagol
哦,抱歉!我错过了关于props更改导致componentDidMount再次触发的部分。非常奇怪。 - ffxsam
@Utro 我计划在 Wrapper 组件的 componentDidMount 中添加一些可重用的功能。上面的代码是在编写该功能之前的,当然我可以将该功能移动到 Wrapped 组件中。在这种情况下,我需要在 Wrapper 组件上使用 componentDidMount - Mas Bagol
请看下面Utro的回答,他是正确的。你错误地写成了connect()(wrap(Wrapper));,但应该是connect()(wrap(Wrapped)); - ffxsam
@ffxsam 抱歉,打错了。我的意思是当 Wrapped 也在那里时会出现问题。我更新了我的问题。 - Mas Bagol
1个回答

1

connect()(wrap(Wrapper)); <-- 替换为 Wrapped

我已测试过,它可以正常工作。

function wrap(Wrapped) {
  class Wrapper extends React.Component {
    componentDidMount() {
      console.log('wrapper component mounted');
    }
    render() {
      return <Wrapped {...this.props}/>
    }
    componentDidUpdate(prevProps, prevState){
        console.log(this.props);
    }
  }
  return Wrapper;
}
class Wrapped extends React.Component {
  componentDidMount() {
    console.log('wrapped component mounted');
  }
  componentDidUpdate(prevProps, prevState){
      console.log(this.props);
  }
  render() {
    return <div></div>;
  }
}

connect(state=>({state}))(wrap(Wrapped));

wrap函数返回Wrapper对象,你不能把Wrapper对象传递给wrap函数。这会导致循环调用。


抱歉,在输入问题时我错过了一些内容。我已经更新了问题。 - Mas Bagol
但它只在 componentDidMount 被调用一次。 - Kokovin Vladislav
你确定吗?你是怎么测试的?在我的情况下,它每次都被调用。 - Mas Bagol
我通过connect传递状态,然后改变状态,以便在包装组件中接收新的props。 - Kokovin Vladislav
我明白了。我的做法是通过 react-hot-loader 直接在代码中更改 props。因为没有高阶组件,当我编辑 props 时,componentDidMount 不会被调用,而 hot-loader 会更新。所以,这样就没有问题了。 - Mas Bagol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接