Search code examples
reactjsreduxreact-hooks

React Redux does not have time to work on first render because of useEffect


I take a name from the path and give it to useeffect->dispatch and if array empty navigate to='', if not empty must show array. Navigate always works on the first render, the second time work normally. I'm trying to change useEffect to useLayoutEffect, but it also works on the first render.

file

const { car } = useParams();
const { carArray } = useSelector(state => state.carStore);
useEffect(() => {
   dispatch(getCar(JSON.stringify(car)))
}, [car])

 return (<div>
{!carArray ? <Navigate to={"/"} : carArray.map..}
</div>)

api

export const getCar = createAsyncThunk(
   'get/car',
   async (str) => {
      const response = await axios.post("", str)
         .then((r) => {
            return r.data
         })
         .catch((err) => {
            console.log(err)
         })
      return response
   }
)

slice

builder.addCase(getCar.fulfilled, (state, action) => {
         state.carArray = action.payload
      })

console.log works like this

enter image description here


Solution

  • This is because returning JSX always happens before useEffect, one solution is to create a state to handle the "loading" phase (the first render):

    const [loading, setLoading] = useState(true);
    //...
    useEffect(() => {
        dispatch(getCar(JSON.stringify(car)));
        setLoading(false);
    }, [car]);
    //...
    if (loading) {
        return <div>Loading...</div>;
    } else {
        return (<div>
        {!carArray ? <Navigate to={"/"} : carArray.map..}
        </div>)
    }
    
    

    If your goal is to get the data during the first render, then useEffect is not the right way to go,it runs after the first render so it is abvious that the redux state is still an empty array then.

    You have mentionned useLayoutEffect but it will not help achieving what you want, the only way is to dispatch getCar action earlier, before the component mounts, geting the id to pass to the function won't be a problem.