Tohmaxxx
Tohmaxxx

Reputation: 434

Create Dynamic Components

I want to dynamically create a component, when I implement something like this:

const gen_Comp = (my_spec) => (props) => {
    return <h1>{my_spec} {props.txt}</h1>;
}

const App = () => {
    const Comp = gen_Comp("Hello");
    return (
        <Comp txt="World" />
    );
}

Something goes wrong (what exactly goes wrong is hard to explain because it's specific to my app, point is that I must be doing something wrong, because I seem to be losing state as my component gets rerendered). I also tried this with React.createElement, but the problem remains.

So, what is the proper way to create components at runtime?

Upvotes: 1

Views: 351

Answers (1)

Nicholas Tower
Nicholas Tower

Reputation: 84902

The main way that react tells whether it needs to mount/unmount components is by the component type (the second way is keys). Every time App renders, you call gen_Comp and create a new type of component. It may have the same functionality as the previous one, but it's a new component and so react is forced to unmount the instance of the old component type and mount one of the new type.

You need to create your component types just once. If you can, i recommend you use your factory outside of rendering, so it runs just when the module loads:

const gen_Comp = (my_spec) => (props) => {
    return <h1>{my_spec} {props.txt}</h1>;
}
const Comp = gen_Comp("Hello");

const App = () => {
    return (
        <Comp txt="World" />
    );
}

If it absolutely needs to be done inside the rendering of a component (say, it depends on props), then you will need to memoize it:

const gen_Comp = (my_spec) => (props) => {
    return <h1>{my_spec} {props.txt}</h1>;
}

const App = ({ spec }) => {
    const Comp = useMemo(() => {
      return gen_Comp(spec);
    }, [spec]);
    return (
        <Comp txt="World" />
    );
}

Upvotes: 2

Related Questions