简体   繁体   中英

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?

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? And what if the props passed to MyComponent changes. 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) . 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. 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).

For completeness: Even when the component is re-rendered, that doesn't necessarily mean all of the DOM nodes for it are recreated; 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):

 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 . After that, React updated that existing component instance five times with the counter values 1 through 5 (I used 5 instead of 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM