Different Supported Value Types that Can Be Rendered in React

When talking about rendering in React, there are primarily two ways in which a certain type of value can be rendered in the DOM. Let’s look at the two ways first and then we will cover what are the different types of values or arguments supported by those two ways via which we can render something.

Two Ways to Render

The first way to render something is the render method itself on ReactDOM (pre-v18) or ReactDOMRoot (since v18).

// Before 18
ReactDOM.render(<h1>Hello React!</h1>, document.querySelector('#root'));

// Since 18
ReactDOM
  .createRoot(document.querySelector('#root'))
  .render(<h1>Hello React!</h1>);

The other render approach is returning a value from the render method of a Class component or if using a Functional component, then directly returning the value from the function.

function ParentComponent(props) {
  return <h1>Hello World</h1>;
}

// or

class ParentComponent extends React.Component {
  render() {
    return <h1>Hello World</h1>;
  }
}

In these examples we “rendered” a React element representing a DOM or HTML tag. You may wonder that apart from this, what other types of values are supported by React that can be rendered ? Let’s go through them.

Supported Renderable Value Types

The first argument to ReactDOM.render or a component’s return value can be of the following types.

React Elements

We just saw an example of this above where we returned/rendered a React element that represented a DOM/HTML tag. React elements can also represent user-defined components. So we could have something like this:

function ParentComponent() {
  // ...
  return (
    <ChildComponent>
      <h1>Hello React!</h1>
    <ChildComponent>
  );
}

In the example above we render or return a React element that represents a user-defined component called ChildComponent which contains an <h1> child.

Fragments

React doesn’t allow rendering of multiple siblings. If you want to render multiple (sibling) React elements (DOM tags or components), then they must be wrapped in a single parent element. One of the problem that occurs with this is that the parent element also gets rendered in the DOM.

React Fragments solves this by providing the ability to return multiple elements (group of children) without adding or rendering any extra node in the DOM. Hence, Fragments are another type of value that you can render or return from components.

render() {
  return (
    <React.Fragment>
      <h1>Hello React!</h1>
      <p>A JavaScript library for building user interfaces</p>
    </React.Fragment>
  );
}

Fragments have a shorter syntax as well (<></>):

ReactDOMClient
  .createRoot(document.getElementById('root'))
  .render(
    <>
      <h1>Hello React!</h1>
      <p>A JavaScript library for building user interfaces</p>
    </>
  );

Just to repeat, the Fragment tags themselves don’t render or represent anything in the DOM. Only the children will eventually make it to the DOM.

Portals

React Portals provide an excellent way to render children into a DOM node which is not a part of the component that is rendering the portal. Another way to think about it is rendering some elements in the DOM in a hierarchically different subtree altogether.

ReactDOMClient
  .createRoot(document.getElementById('root'))
  .render(
    ReactDOM.createPortal(
      // ChildComponent will be rendered inside #modal and not #root
      <ChildComponent />,
      document.querySelector('#modal')
    ))
  );

// or

function ParentComponent(props) {
  // ...
  return ReactDOM.createPortal(
    // ChildComponent will be rendered inside #modal and not ParentComponent
    <ChildComponent />,
    document.querySelector('#modal')
  );
}

Some Primitive Values

We can render strings and numbers that’d render as text nodes in the DOM.

// Strings
ReactDOM
  .createRoot(document.getElementById('root'))
  .render('Hello React!');

// Numbers
ReactDOM
  .createRoot(document.getElementById('root'))
  .render(1010101010);

We can also return a Boolean or null value. They render nothing and hence are useful for conditional rendering.

// If isMobile is false then `false` will be returned
// which will render nothing
return isMobile && <MobileComponent />;

Arrays

React allows rendering of arrays as well that can contain one or more types of values described above.

ReactDOMClient
  .createRoot(document.getElementById('root'))
  .render(
    [
      <ChildComponent />,
      <>
        <h1>Hello React!</h1>
        <p>A JavaScript library for building user interfaces</p>
      </>,
      'Hello React!',
      101010,
      null
    ]
  );

Note: Arrays allows us to render multiple sibling elements from a component, similar to Fragments.

When rendering an array of values, the React Elements value types (representing components or DOM tags) must have a key prop associated with them.

Unsupported Value Types

If you randomly tried to render unsupported types then React would throw errors.

// Warning: Functions are not valid as a React child.
render(() => {});

// Uncaught Error: Objects are not valid as a React child (found: object with keys {}). If you meant to render a collection of children, use an array instead.
render({});

Leave a Reply

Your email address will not be published.