简体   繁体   English

如果我从某个方法返回组件的 jsx 并在另一个组件的渲染中调用该方法,那么每次渲染时都会创建一个新对象吗?

[英]If I return jsx of a Component from some method and call that method in another component's render, then is a new object created on every render?

If I return jsx of a Component from some method and call that method in another component's render, then is a new object created on every render?如果我从某个方法返回组件的 jsx 并在另一个组件的渲染中调用该方法,那么每次渲染时都会创建一个新对象吗?

class MyComponent extends React.Component {
  render = () =>(<h3>My Component</h3>)
}

function getEl(){ return (<MyComponent />) }

class Comp extends React.Component{
 componentDidMount = () =>{ 
   let ct = 100;
   const update = () => {
    if(ct-- < 0) return;
    this.setState({}, update);
   }
   update();
 } 
 render(){
  return (<div> {getEl()} </div>)
 }
}

If Comp renders 100 times, is a new instance of MyComponent created 100 times?如果 Comp 渲染 100 次,是否创建了 100 次 MyComponent 的新实例? And what if the props passed to MyComponent changes.如果传递给 MyComponent 的道具发生变化怎么办。 Then?然后? Looking for some good in-depth explanation of why this happens寻找一些很好的深入解释为什么会发生这种情况

This stuff can be really confusing at first.这些东西一开始真的很令人困惑。 Or even after you've done your first few bits of work.或者甚至在您完成最初的几项工作之后。 :-) :-)

The JSX <MyComponent /> is shorthand for React.createElement(MyComponent) . JSX <MyComponent />React.createElement(MyComponent)简写。 What that does is create an object (a "React element") giving React the information it needs to create or update an instance of the component.它所做的是创建一个对象(一个“React 元素”),为 React 提供创建或更新组件实例所需的信息。 It doesn't always create a new component instance;它并不总是创建一个新的组件实例; if an instance already exists for where that object is used to render something, the previous instance is updated.如果该对象用于渲染某些内容的实例已经存在,则更新前一个实例。 The object from the JSX itself isn't the component (and in fact, you can reuse them). JSX 本身的对象不是组件(事实上,您可以重用它们)。

For completeness: Even when the component is re-rendered, that doesn't necessarily mean all of the DOM nodes for it are recreated;为了完整性:即使重新渲染组件,也不一定意味着重新创建它的所有 DOM 节点; they may be updated or, if it's an unnecessary render, left completely alone.它们可能会更新,或者,如果它是不必要的渲染,则完全保留。

Let's expand that code to include a prop on MyComponent and throw some instrumenting calls at it (fancy talk for console.log and a MutationObserver in this case):让我们扩展该代码以在MyComponent上包含一个 prop 并对其进行一些检测调用(在这种情况下, console.logMutationObserver花哨谈话):

 class MyComponent extends React.Component { constructor(props) { super(props); console.log(`MyComponent constructor, counter = ${this.props.counter}`); } render() { const { counter } = this.props; console.log(`MyComponent render, counter = ${counter}`); return <h3>My Component: {counter}</h3>; } } function getEl(counter) { console.log(`getEl, counter = ${counter}`); return <MyComponent counter={counter} />; } class Comp extends React.Component { constructor(props) { super(props); this.state = { counter: 0, }; } componentDidMount() { let counter = 0; const handle = setInterval(() => { ++counter; this.setState({counter}); if (counter === 5) { clearInterval(handle); } }, 250); } render() { const { counter } = this.state; console.log(`Comp render, counter = ${counter}`); return <div>{getEl(counter)}</div>; } } const root = document.getElementById("root"); const ob = new MutationObserver(records => { for (const record of records) { console.log(`DOM modification type: ${record.type} on ${record.target.nodeName}:`); if (record.type === "characterData") { console.log(`* Value: Changed from ${record.oldValue} to ${record.target.nodeValue}`); } else if (record.type === "attributes") { // We aren't listening for these } else { for (const node of record.removedNodes) { console.log(`* Removed: ${node.nodeName} with ${node.innerHTML || node.nodeValue || "(no value)"}`); } for (const node of record.addedNodes) { console.log(`* Added: ${node.nodeName} with ${node.innerHTML || node.nodeValue || "(no value)"}`); } } } }); ob.observe(root, { childList: true, subtree: true, characterData: true, characterDataOldValue: true }); ReactDOM.render(<Comp/>, root);
 <div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js"></script>

As you can see, the MyComponent constructor was only called once to create a single instance of MyComponent , initially with counter = 0 .如您所见, MyComponent构造函数仅被调用一次以创建MyComponent的单个实例,最初使用counter = 0 After that, React updated that existing component instance five times with the counter values 1 through 5 (I used 5 instead of 100).之后,React 使用计数器值 1 到 5(我使用 5 而不是 100)更新了现有组件实例五次。

You can also see the DOM modifications thanks to the MutationObserver : The root component gets a new H3 with a couple of text nodes with the initial text, and then just the text node with the counter is updated as the counter changes.由于MutationObserver您还可以看到 DOM 修改:根组件获得一个新的 H3,其中包含几个带有初始文本的文本节点,然后随着计数器的变化,仅更新带有计数器的文本节点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将JSX从组件方法返回到渲染方法 - Return JSX from component method to render method 如何从另一个组件调用React的render方法()? - How to call React's render method() from another component? 从render方法中的嵌套函数中反映调用组件的方法 - React call component's method from nested function in render method ReactJS,如何在另一个组件的render方法中渲染一个组件? - ReactJS, how to render a component within another component's render method? 功能组件定义在类组件的 render() 方法中,状态在通过 JSX 创建时重置,但在直接调用时不会重置 - Functional component definition inside class component's render() method, state resets when created through JSX, but not when called directly ReactJS,新的 axios 在组件的每次渲染时调用 - ReactJS, new axios call at every render of the component 如何从React组件的render方法获取纯文本或将JSX.Element转换为字符串? - How can I get the plain text from the render method from React component or convert a JSX.Element to string? 由另一个 function 组件渲染一个 JSX 部件 - reactJS - render a part JSX by another function component - reactJS 如何在React中的render方法之外的函数中渲染组件? - How to render component from a function outside the render method in React? React / Flux:从组件的渲染方法触发操作还是从组件执行Rest调用? - React/Flux: Firing an action from a render method of an component or doing a Rest call from a component?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM