Monday, 3 April 2023

Does multiple setState at once guarantee to be happened at once in react hooks?

I have below piece of code

import React, { useEffect, useState } from 'react';
const Mycomp = () => {
  const [firstState, setFirstState] = useState(0);
  const [secondState, setSecondState] = useState(0);
  const [thirdState, setThirdState] = useState([]);

  useEffect(() => {
    console.log(thirdState);
    console.log(firstState);
    console.log(secondState);
  }, [thirdState])

  const onClick = () => {
    setThirdState(["something"])
    setFirstState(1)
    setSecondState(2)
  }

  return (
    <div>
      <button onClick={onClick}>Submit</button>
    </div>
  );
};

export default Mycomp;

I have two questions here

  1. Is it possible that as I have written setThirdState at the first in onClick function then it gets called & set the state and call the useEffect and I do not get updated firstState & secondState?
  2. Is it good to use array as dependency in useEffect. If not, then what is the other option?

Edit: Here is my use case

const Mycomponent = () => {
    const [clipcount, setClipcount] = useState(0);
    const [clipsDetails, setClipsDetails] = useState([]);
    const [activePage, setActivePage] = useState(1);
    const [socketClipCount, setSocketClipCount] = useState(0);

    useEffect(() => {
    webhookSocket.on(`livecut${id}`, (data) => {
      setSocketClipCount((socketClipCount) => socketClipCount + 1);
    });
  }, [webhookSocket]);

    useEffect(() => {
        getClips();
    }, [activePage])

    const getClips = async () => {
        const { value } = await getAllClips({
            limit: clipLimit,
            pageNo: activePage,
            sort: { _id: -1 },
        });
        if (value?.success) {
            setClipcount(value.totalLength);
            setClipsDetails([...clipsDetails, ...value?.clips]);
        }
    };

    return (
        <div className="custom-generated-clips styled-scroll">
            {socketClipCount && <button onClick={() => {
                setSocketClipCount(0);
                setClipsDetails([]);
                setActivePage(1);
            }}>
                Refresh
            </button>}
            <InfiniteScroll
                dataLength={clipsDetails?.length}
                hasMore={clipsDetails?.length < clipcount ? true : false}
                next={() => setActivePage(activePage + 1)}
                loader={
                    <div className="InfinitScrollLoadingBottom">
                        <div className="InfinitScrollLoadingBottomText">Loading...</div>
                    </div>
                }
                endMessage={
                    <div className="InfinitScrollEndBottom">
                        <div className="InfinitScrollEndBottomText">
                            {clipsDetails?.length > 4 ? "You've reached End!" : ""}
                        </div>
                    </div>
                }
                // pullDownToRefreshThreshold={limit}
                scrollableTarget="scrollableDiv"
            >
                {myData}
            </InfiniteScroll>
        </div>
    )
};

export default Mycomponent;

So here I am getting clipDetails and showing it in Infinite scroll which is simple thing. Now when I get clips from socket I show the Refresh button and refreshing that section by setting setSocketClipCount(0);setClipsDetails([]);setActivePage(1); but it does not set the state for the clipDetails & socketClipCount array.

What could be the solution for it? I am using React 18 even batch updating is not working.

It is hard for me to get things because sometimes React official docs says

  1. It is not good to club the state like useState({ state1: "", state2: "" })
  2. React 18 supports batch update still the above code does not work.


from Does multiple setState at once guarantee to be happened at once in react hooks?

No comments:

Post a Comment