[英]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.log
和MutationObserver
花哨谈话):
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.