Is there a React equivalent of Vue's nextTick() function?
Asked Answered
Z

5

16

Vue has this nextTick function, which is an async function that waits until the DOM is flushed. This is particularly useful when you want to perform some operation directly upon an element, like scrolling a DIV with scroll(). This avoids the need to wrap this call into a blind setTimeout().

In React I resorted to setTimeout() in the past. Is there an equivalent to nextTick(), or any better way to do it?

Zuckerman answered 21/6, 2022 at 16:59 Comment(0)
C
11

In this case it's possible to use setTimeout to achieve this goal.

See: https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#late_timeouts

Because it will execute function given in parameter in the end of the current thread, it's close to the behaviour of Vue.nextTick.

Example : https://codesandbox.io/s/gallant-roman-y0b9un?file=/src/App.js

Ci answered 9/2, 2023 at 20:0 Comment(3)
I was unaware of calling setTimeout without specifying the delay. That's pretty much it.Zuckerman
Thats pretty cool actually, however i dont think its the best react approach :D but cool trick indeedTreasonous
After several years of experience of facing this issue occasionally, mostly to do with focus/select/interact with dom elements upon state update/create conditionally on demand. useEffect is never the cleanest solution even the most wrong solution sometimes as it will run regardless all the complex situation. otherwise you have to do tons of complex dom element ref check, as React18 will run useEffect twice in strict dev mode, it brings extra development overhead to handle this problem. This answer is the probably closest and yet the disappointed one we can get for React FC.Carrington
S
6

You can use reactHooks to work with the lifecycle of your application.

In your functional component:

import React, { useEffect } from 'React'

useEffect(() => {
   // your method
}, []);

This will render in the first render.

You can set dependencies to be listened to when its changes.

import React, { useEffect } from 'React'

useEffect(() => {
   // your method
}, [yourDependence]); //it will run every yourDependence change and the first time.
Schmo answered 21/6, 2022 at 17:34 Comment(0)
M
3

Using setTimeout didn't work for me because I needed to run a function that was closing over the props which means the out of date version of the function would run after the given timeout.

This is what I came up with instead:

const useEffectOnNextRender = (callback: React.EffectCallback) => {
    const [scheduled, setScheduled] = useState(false);

    useEffect(() => {
        if (!scheduled) {
            return;
        }

        setScheduled(false);
        callback();
    }, [scheduled]);

    return () => setScheduled(true);
};

And here's the way to use this hook:

function DemoComponent() {
    const [count, setCount] = useState(0);

    const scheduleDisplay = useEffectOnNextRender(() => {
        display();
    });

    const incrementAndDisplay = () => {
        setCount(count + 1);
        scheduleDisplay();
    };

    const display = () => {
        console.log(count);
    };

    return (
        <div>
            <div>{count}</div>
            <button onClick={incrementAndDisplay}>increment and display</button>
        </div>
    );
}

Notice the scheduleDisplay() call in the incrementAndDisplay function. If I just called display() an out of date value of the count variable would be logged.

Obviously this is an overly simplified example which is just meant to demonstrate the point.

Thought I would share, maybe it'll help someone in the future.

Mauritamauritania answered 16/5 at 19:54 Comment(1)
For some cases setTimeout does not work, and this hook is perfect for them, thanks @TKharaishvili!Palladian
I
1

In React class components, you can use the componentDidMount for the 1st render & componentDidUpdate for the subsequent renders, to perform DOM updates.

componentDidMount

Initialization that requires DOM nodes should go here.

See https://reactjs.org/docs/react-component.html#componentdidmount

componentDidUpdate

Use this as an opportunity to operate on the DOM when the component has been updated.

See https://reactjs.org/docs/react-component.html#componentdidupdate

For functional components, there is the useEffect hook.

See https://reactjs.org/docs/hooks-effect.html

Insula answered 21/6, 2022 at 17:26 Comment(0)
G
1

Now, you can use a native method from JavaScript called queueMicrotask, read more about it here

Gawk answered 5/6 at 18:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.