const App = () => {
return React.createElement(
"div",
{},
React.createElement('h1', {}, "Adopt The Pet"))
}
}
ReactDOM.render(App(), document.getElementById("root")); // this works
// vs
ReactDOM.render(React.createElement(App), document.getElementById("root"));
I am following an introduction to react course in which the author uses the second version with a new React.createElement()
wrapper. I can't figure out the need to do so even after going through the relevant react docs.
The first version already returns a React.createElement()
so why not use that returned element instead of wrapping it inside a new React.createElement()
?
Edit: Even the React documentation uses the course author's method if you translate the doc's JSX to React.createElement()
calls but again, they haven't explained why.
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
// React.createElement(Welcome, {name : Sara})
const element = <Welcome name="Sara" />;
// Why not just do this?
const element = Welcome({Sara})
ReactDOM.render(
element,
document.getElementById('root')
);
This has to do with what a "React component" actually is. According to the React documentation:
Conceptually, components are like JavaScript functions. They accept arbitrary inputs (called “props”) and return React elements describing what should appear on the screen. - https://reactjs.org/docs/components-and-props.html
Boiling that down I understand a React component to be "a function that returns a React element" (ignoring classes altogether for now).
function component() {
return React.createElement('h1', null, 'Hello World')
}
So if that's the case, we should be able to pass our React component directly to ReactDOM.render()
or React.createElement()
:
ReactDOM.render(component, document.getElementById("root"))
// or
React.createElement('div', null, component)
But we can't. This doesn't work. It gives us the following error:
Warning: Functions are not valid as a React child. This may happen if you return a Component instead of from render. Or maybe you meant to call this function rather than return it.
Sure, we can fix this by invoking our function:
ReactDOM.render(component(), document.getElementById("root"))
// or
React.createElement('div', null, component())
But is that really a React component? No. It's just invoking a plain old function to ultimately get a React element as the return value. To illustrate this point further, look what happens when we try and use the useState
hook:
function component() {
const [state, setState] = React.useState(0);
return React.createElement('h1', null, 'Hello World')
}
ReactDOM.render(component(), document.getElementById("root"))
Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
But wait a minute, we thought we had a function React component?
A function that returns a React element does not become a "React component" until it is passed as the first argument to React.createElement()
.
This makes sense if we think about it. If you define a function, there's no way for React to know that your function is a React component. You pass the function as reference, but React doesn't know that what you're passing will ultimately return a React element (per our definition). We need to somehow indicate to React that our function is indeed a "React component." We do this by passing. our function as the first argument to React.createElement()
// Regular old function
function component() {
return React.createElement('h1', null, 'Hello World')
}
// becomes a React component
React.createElement(component)
This, among other things like the useState()
hook above, is also required for React to take control of the props passed as arguments to our function, so it can re-render when our props change. We have to give React control of our function. So, to amend our previous definition of what a React element is, we land here:
A React component is "a function that returns a React element and is passed as the first argument to React.createElement()"
When we use JSX this is all abstracted away, so I assume that why people don't really talk about it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With