Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What actually happens when React component returns?

I have noticed a difference between the data before returning and after a return of a component.

before renderafter render

class AComponent extends Component {
  render() {
    const body = <BComponent crmStatus={...}/>
    debugger // log body on the right
    // ... render as static html to electron window
    return false
  }
}

class BComponent extends Component {
  render() {
    const resultRender = <article className='large'>...</article>
    debugger // log resultRender on the left
    return resultRender
  }
}

My former question was going to be "How to read rendered component's className?", but I have split the questions as answering what is actually happening and why is it like that really started to bug me and might even give me hints to solve my problem.

So the question is:

What is actually happening to the component and why is it like that? I can have really complicated logic in my render() function, but I guess working with the components isn't that easy.

const headerContact = isContactInCRM ? <p>..</p> : <div>..</div>
const headerCallBtnsOrInfo = isSipEnabled && <div>..buttons..</div>
const callTimer = callDuration && <span>{callDuration}</span>
const footerNotes = <footer>..</footer>
const someImportedComponent = <MyComponent />

const resultRender = <section>
  {headerContact}
  {headerCallBtnsOrInfo}
  {callTimer}
  {footerNotes}
  {someImportedComponent}
</section>

// there is a difference in data between headerContact and someImportedComponent
// when traversing the resultRender's tree in console 
like image 835
Qwerty Avatar asked May 20 '16 12:05

Qwerty


1 Answers

Before answering the question, it's worth to look at what is JSX. It just provides syntactic sugar for the React.createElement(component, props, ...children) function.

<div>
  <MyComponent/>
</div>

As an example, above JSX snippet will be transformed to following JavaScript code in the compilation process.

React.createElement(
  "div",
  null,
  React.createElement(MyComponent, null)
);

You can try out this using Babel online repl tool. So if we rewrite your example code using normal JavaScript (after compiling JSX), it will be something like this.

class AComponent extends Component {
  render() {
    const body = React.createElement(BComponent, { crmStatus: '...' });
    debugger // log body on the right
    // ... render as static html to electron window
    return false
  }
}

class BComponent extends Component {
  render() {
    const resultRender = React.createElement('article',{ className: 'large' }, '...' );
    debugger // log resultRender on the left
    return resultRender
  }
}

By looking at above code, we can understand that <BComponent crmStatus={...}/> doesn't create a new object of BComponent class or call render method of BComponent. It just create a ReactElement with BComponent type and crmStatus prop. So what is a ReactElement? ReactElement is a pain JavaScript object with some properties. I recommend you to read this post from official React blog to get an in-depth understanding of React components, elements, and instances.

An element is a plain object describing a component instance or DOM node and its desired properties. It contains only information about the component type (for example, a Button), its properties (for example, its color), and any child elements inside it.

Basically, what you have printed in the console is two React elements in different types. The left one is describing DOM node with type 'article' and the right one is describing BComponent type React component instance. So simply you can't expect them to be the same.

Then where does React create an instance of BComponent? Actually, this happens internally in the React code. Usually, we don't have access to these instances or what return by their render methods in our application code.

However, React still provide an escape hatch called 'refs' which you can explicitly access instances of child components. You might be able to use that approach to solve your original problem.

Hope this helps!

like image 147
Tharaka Wijebandara Avatar answered Sep 22 '22 15:09

Tharaka Wijebandara