React Redux在第一次渲染时由于`useEffect`而没有足够的时间来工作。

huangapple go评论61阅读模式
英文:

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

React Redux在第一次渲染时由于`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 =&gt; state.carStore);
useEffect(() =&gt; {
   dispatch(getCar(JSON.stringify(car)))
}, [car])

 return (&lt;div&gt;
{!carArray ? &lt;Navigate to={&quot;/&quot;} : carArray.map..}
&lt;/div&gt;)

api

export const getCar = createAsyncThunk(
   &#39;get/car&#39;,
   async (str) =&gt; {
      const response = await axios.post(&quot;&quot;, str)
         .then((r) =&gt; {
            return r.data
         })
         .catch((err) =&gt; {
            console.log(err)
         })
      return response
   }
)

slice

builder.addCase(getCar.fulfilled, (state, action) =&gt; {
         state.carArray = action.payload
      })

console.log works like this

React Redux在第一次渲染时由于`useEffect`而没有足够的时间来工作。

答案1

得分: 2

这是因为返回JSX总是发生在useEffect之前,一个解决方案是创建一个状态来处理“加载”阶段(第一次渲染):

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

如果你的目标是在第一次渲染期间获取数据,那么useEffect不是正确的方法,它在第一次渲染之后运行,所以明显Redux状态仍然是一个空数组。你提到了useLayoutEffect,但它不会帮助你实现你想要的效果,唯一的方法是在组件挂载之前提前调度getCar动作,获取要传递给该函数的ID不会成为问题。

英文:

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(() =&gt; {
    dispatch(getCar(JSON.stringify(car)));
    setLoading(false);
}, [car]);
//...
if (loading) {
    return &lt;div&gt;Loading...&lt;/div&gt;;
} else {
    return (&lt;div&gt;
    {!carArray ? &lt;Navigate to={&quot;/&quot;} : carArray.map..}
    &lt;/div&gt;)
}

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.<br>

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.

huangapple
  • 本文由 发表于 2023年5月15日 02:38:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76249113.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定