Help useEffect React Hooks

Hi, I need some help with the useEffect…

Well… It’s more a question than help.

I’m using useEffect to be like the componentDidUpdate lifecycle… I need to re-render/update everytime that the prop time updates… It works fine, It does what I need to, but the problem is with eslint, it shows me a error saying react-hooks/exhaustive-deps, I researched it. The second argument array it suppose to have all the props and state of the component so It can re-render/updates everytime some of those arguments (array values) changes, but the thing is that I just need to update everytime the prop time changes. Because if I add all my props to that array, it re-renders/update every number of props times (If I have 4 props, it will update 4 times)

So how can I do that?

function Timer(props) {
    useEffect(() => {
        const timerLoaderProgress = (props.passedTime * 100) / props.totalTime;
        const timerLoader = document.querySelector(".timer-loader");
        timerLoader.style.width = timerLoaderProgress + "%";

        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [props.time]);

    return (
        <div
            className={`timer-wrapper ${props.isEnding ? "timer-to-end" : ""}`}
        >
            <div className="timer-loader"></div>
            <p id="timer-label">{props.status ? "Session" : "Break"}</p>
            <div id="time-left">{props.time}</div>
        </div>
    );
}

It should do that anyway. Anytime props or state updates, the component should update.

        const timerLoader = document.querySelector(".timer-loader");
        timerLoader.style.width = timerLoaderProgress + "%";

Noooooooooooooooooo!!!

Don’t manipulate the DOM. The point of React is that you put React in charge of it. It’s like hiring a money manager but then go behind his back and start changing the accounts around and changing investments, etc. How is your accountant supposed to have any idea what is going on? How is React supposed to know that you messed with the virtual DOM and know to update the actual DOM? The way it knows that is (in part) by monitoring props and state.

If you want to change that width, you should have useEffect update a state variable and use that state variable to generate that style value. You have to let React do it. Or don’t use React.

6 Likes

HAHAHAHAHA I really liked that analogy. I think I know how I could fix it. Or at least I understood what you said.

But I still have the same question. How I can avoid the component to re-render everytime one of the props changes. Cause if I add of all my props to the second argument of useEffect() (the array), it re-renders like 3 times when I just need it to re-render when the props.time changes. i.e., for every prop update it re-renders like 3 times.

Also, the code works, but It shows an error (as you can see I disable it), and that error ask me to put ALL my props and state in that array.

Or maybe I’m not getting it… I mean, does the component re-render those extra 3 times, or the useEffect function its called every number of props/state times. Maybe that could be my confusion. :thinking:

I was thinking in adding a state to that functional component, and then update it using useEffect. The thing is that it would be the same, I would have to add all my props and the state to the array of useEffect.

Welp, React docs, here i go.

wouldnt the component rerender everytime the props change. In this case any calculations you make would be reevaluated and then passed properly to the rendered components. I see you change the width of the “time-loader” component. SInce its part of the jsx, you could simply put the value in the inline styles. The flow would be- your parent gets new props, it calculates the width, then pass that width to the child component in the inline styles. On paper, i dont think useEffect is requried here, unless im missing part of the functionality

1 Like

You can either update all variables at the same time, or you can wrap it in React.memo and give it a callback to control when it updates.

The other possibility is to not worry about it. There is the old saying that premature optimization is the root of all evil. Often we obsess about optimization in places where it doesn’t matter. Most web apps spend more than 99% of their time waiting for input. Make smart choices, but don’t obsess over micro optimizations unless there is a need.

when I just need it to re-render when the props.time changes

That would be a good argument for React.memo.

1 Like

I though in that solution too :joy:, yesterday when I was just falling sleep that idea come to mind… And well, it works just fine. Thanks for the help.

I will read about React.memo, but either way, I solved my problem passing the calculated width as a prop and I also fixed the thing about cheating on my money manager. :joy:

Thanks for all the help.

function Timer(props) {
    return (
        <div
            className={`timer-wrapper ${props.isEnding ? "timer-to-end" : ""}`}
        >
            <div
                className="timer-loader"
                style={{ width: props.loaderWidth + "%" }}
            ></div>
            <p id="timer-label">{props.status ? "Session" : "Break"}</p>
            <div id="time-left">{props.time}</div>
        </div>
    );
}

Well, if they’re all coming in on props, then that’s a perfect case for React.memo.

Initially, it is hard to realize when is a good time to use useEffect, as they say, its meant to trigger rerender for example, following some side effects, but what are those side effects, its hard to define when new to the notion :slight_smile: . A side effect could be something asynchronously, for example, if you send a request to a server, expect some result and once the result returns, change the state of the component, which uses that result data in order to rerender it.

Well, technically it does also include DOM manipulation. Like the example given in the useEffect docs of setting the page title.

But I do agree that plain DOM manipulation should be avoided. You can query the DOM (but a ref is better) but you shouldn’t update the DOM content manually (there might be edge cases where it is needed, although I’m not really sure).

2 Likes

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.