如果我将组件作为道具传递,则何时渲染?

时间:2019-06-04 19:54:45

标签: javascript reactjs

我有一个React应用程序。在我的应用中,我通常希望我的视图组件不要直接导入其他react组件。相反,我希望视图的父容器组件负责收集依赖项,并通过props将依赖项注入到视图中。

通常如下所示:

// Container.js

import SomeOtherComponent from '/somewhere'
import View from './View'

class Container extends React.Component {
    render() {
        return(
            <View
               component={<SomeOtherComponent/>}
            />
        )
    }
}

// View.js
const View = props => (
    <div>
        {props.component}
    </div>
)

但是请注意,当作为道具传递给View时,SomeOtherComponent看起来是如何被实例化的。

这是否意味着在View之前实例化SomeOtherComponent(因此要经历所有相关的生命周期方法)?

或者SomeOtherComponent仅在实例化View并调用View的render方法时实例化吗?

3 个答案:

答案 0 :(得分:2)

这取决于您“实例化”的意思。 <SomeOtherComponent/>被转译为React.createElement(SomeOtherComponent, null),因此如果实例化意味着调用React.createElement,则它将在Container的渲染期间发生。

但是,我认为这不是一件非常有意义的事情。 React.createElement所做的只是生成一个描述要渲染内容的小对象。该对象将大致像这样(我省略了一些东西):

{
  type: SomeOtherComponent,
  props: null,
  key: null,
  ref: null,
}

仅创建这些对象就不会导致安装任何组件或经历整个生命周期。相反,它们必须由render函数返回。在您的情况下,更重要的是,Container不是将其作为渲染对象返回,而是作为传递的道具。因此,在Container调用render之后,react将看到它应该挂载一个View。它这样做是从上方将对象作为道具传递。然后,此新安装的视图将呈现,并作为其一部分最终返回对象。只有在这时,React才会安装该组件。

因此,如果“实例化”表示“已安装”,则它将首先开始安装Container,然后是View,然后是SomeOtherComponent。 SomeOtherComponent首先完成安装,然后完成View,然后完成Container。

答案 1 :(得分:1)

constructorrender方法以正确的顺序运行。 componentDidMount按照您的描述运行。

查看https://codesandbox.io/s/lucid-benz-c6hlb中的日志

答案 2 :(得分:0)

当您显示相应的视图时,它将被实例化。发生这种情况是因为组件会对DOM中的呈现做出反应,而不仅仅是导入它。 在下一个示例中,如果从App的呈现方法中删除“ {component}”,则NotUsedComponent不会被初始化,并且componentDidMount内部的console.log不会被调用。

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";


class NotUsedComponent extends React.Component {
  componentDidMount() {
    console.log("NotUsedComponent is mounted");
  }
  render() {
    return <div />;
  }
}


function App() {
  const component = <NotUsedComponent />;

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      {component}
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

所以没有渲染-没有初始化。