In React what's the best way to render a Component differently the first time it appears on the page?

Viewed 1201

I have some React Components that are going to be used a lot all over my App.

I'd like that only the first time they get printed in the DOM, they return as

<symbol id="SVGComponent"><SVGComponent></symbol><use href="#SVGComponent" />

while every other following printing should be only <use href="#SVGComponent" /> since the symbol has already been declared in the page

const [firstTime, setFirstTime] = useState(true);

useEffect(() => { setFirstTime(false) }, []);
if (firstTime) {
    return (<symbol id="Component"><Path /></symbol>);
}
else {
    return(<use href="#Component"/>);
}

This is my code so far but the condition always return false.

How is that possibile in React with useEffect? Thanks in advance for your help

3 Answers

It is not that your condition always returns false. The issue is that you change the state immediately after your first render(in the useEffect where you set the state variable value to false) which causes another immediate rerender so you skip the true condition of the variable(you technically don't skip it, you just render the true state and rerender with false straight away after).

If you don't change the state in the mounting useEffect you'll notice that the code works properly. In order to do this, though, you'll have to use useRef which basically enables you to create a variable that persists between rerenders but the mutation of its value doesn't cause a rerender(unlike state variables from useState).

I've added a button to simulate change of state or in other words - simulate a second render:

import React, { useState, useRef, useEffect } from 'react';

function App() {
    const [buttonClicked, setButtonClicked] = useState(false);

    const isFirstRender = useRef(true);

    useEffect(() => {
        isFirstRender.current = false;
    }, []);

    const renderRepresentation = () => {
        if (isFirstRender.current) {
            return (
                <symbol id="Component">
                    <Path />
                </symbol>
            );
        }
        else {
            return (
                <use href="#Component" />
            );
        }
    }

    return (
        <>
            {renderRepresentation()}
            <button onClick={() => setButtonClicked(true)}>SIMULATE STATE CHANGE</button>
        </>
    );
}

And here is a codesandbox demo which you can try.

The component itself won't be able to tell if others of itself exist. You will need to store this information at a higher level in the application, and then tell the component via props whether it is the first instance or not.

So I ended up replying to myself again for anyone coming. Fortunately what I want to achieve is possibile with just a few lines of code. Thanks this guy for the code: https://stackoverflow.com/a/57331421/3937587

let instancesCount = 0
function Component(props) {
        const [firstRender, setFirstRender] = useState(false)
        useEffect(() => {
            setFirstRender(instancesCount === 0)
            instancesCount++
            return () => { instancesCount-- }
        }, [])

        if (firstRender)
           //do something only the first time the component appears

}
Related