cj-
cj-

Reputation: 322

Render before or after child element

How do I render before or after a child element in a container?

I am learning React by integrating it into my own website. I started with this:

function createErrorSection(name, title, description) {
    const section = document.createElement('section');
    const container = document.createElement('div');
    const h2 = document.createElement('h2');
    const p = document.createElement('p');
    section.appendChild(container);
    container.appendChild(h2);
    container.appendChild(p);
    section.id = name;
    section.classList = 'section-error';
    container.classList = 'section-error-container';
    h2.textContent = title;
    p.textContent = description;
    return section;
}

Which I turned into this:

function createErrorSection(name, title, description) {
    return (
        <section id={name} className='section-error'>
            <div className='section-error-container'>
                <h2>{title}</h2>
                <p>{description}</p>
            </div>
        </section>
    );
}

This is eventually propagated down to either node.before(section) or node.after(section).

I checked inside ReactDOM, ReactDOM/server and React with no luck. I saw I could create an HTML string, but I need an HTMLElement and would rather not do my own rendering if it can be avoided (I want to learn the React way, I already know the vanilla way).

My end goal is to learn how and when to use React properly. I'd love to know the proper way, but insight, advice and workarounds are also greatly appreciated!

Upvotes: 1

Views: 1608

Answers (2)

Mikhail Grechka
Mikhail Grechka

Reputation: 735

First of all, component's name should be written in PascalCase.

In React, you should rethink the way you render elements.

There are different approaches for different purposes:

  1. Pass components to the children prop
const Wrapper = ({ children }) => (
  <div className="wrapper">
    <h1>Wrapper heading</h1>
    {children}
  </div>
);

Now you can pass children to the wrapper this way:

const AnotherComponent = () => (
  <Wrapper>
    <div>Element that will be rendered where the children prop is placed</div>. 
  </Wrapper>
);
  1. Pass components to custom props:

If you need to render many components in different spots, you can do this:

const MultiSpotComponent = ({ HeaderComponent, FooterComponent }) => (
  <div>
    {HeaderComponent}

    <div>Some content</div>

    {FooterComponent}
  </div>
);

And then pass your components to the props the same way you do with attributes in HTML:

<MultiSpotComponent HeaderComponent={CustomHeader} FooterComponent={CustomFooter} />

Notice that I used self-closing tag for the component, because I don't render children inside it.

  1. Render list
const AnotherComponent = () => {
  const dynamicArray = ['some', 'dynamic', 'values'];

  return (
    <div>
      {dynamicArray.map(value => <div key={value}>{value}</div>)}
    </div>
  );
};

I have described only 3 most-used approaches, but there are more ways to render elements. You can learn more at Official React Documentation

Upvotes: 1

kruschid
kruschid

Reputation: 779

In React you rather want to create a custom component with a single argument which contains the corresponding properties:

// single argument contains all props
function ErrorSection({name, title, description}) {
    return (
        <section id={name} className='section-error'>
            <div className='section-error-container'>
                <h2>{title}</h2>
                <p>{description}</p>
            </div>
        </section>
    );
}

now you need to import ReactDOM and call render in order to show the component ErrorSecion with some specific property values inside a HTML node with the id #app. Make sure that your HTML document contains such a node.

import ReactDOM from "react-dom";

ReactDOM.render(
  <ErrorSection name="..." title="..." description="..." />,
  document.querySelector("#app")
);

Most of the react apps render some dynamically generated nested components into the DOM using a single empty HTML node inside the document body (e.g. div#app or div#root). So you most likely will only need to have a single ReactDOM.render call in your entire project.

Upvotes: 1

Related Questions