【问题标题】:Redux useSelector not updated, need to be refreshRedux useSelector 没有更新,需要刷新
【发布时间】:2020-04-30 03:42:02
【问题描述】:

我面临这个问题。 当我有一个 Axios 调用时,它承诺调度一个动作来更新 redux 并执行回调。 但是当执行回调时,redux 状态似乎是陈旧的。

i got a sandbox code for demo here

如果点击getNewDate按钮,控制台会显示redux状态的不同。 当 redux 导致重新渲染时,状态将是正确的。

如何在回调期间获得正确的 redux 状态?

【问题讨论】:

    标签: reactjs redux axios


    【解决方案1】:

    响应总是过时的,这就是 React 钩子的工作原理。它们在创建时对每个单独渲染中的所有变量应用闭包。如果您绝对需要该值在回调函数(或效果)中不会过时,请为其设置一个 ref。

    const { response, getNewDate } = useResponse();
    const responseRef = useRef(response);
    useLayoutEffect(() => {
        responseRef.current = response;
    }, [response]);
    const callbackSuccessful = (data: IResponse) => {
        console.log("response is not Stale: " + responseRef.current.newDate);
        console.log("should be: " + data.newDate);
    };
    

    设置 ref 后,您会清楚地看到响应实际上正在发生变化,并且 responseRef.current 显示的值与 data.newDate 相同。

    你必须在这里使用LayoutEffect,因为效果运行的顺序对于回调是错误的。由于 useEffect 在组件重新渲染后运行,而 useLayoutEffect 在组件重新渲染时运行。

    您可以通过另一种方式看到 useSelector 工作正常并且正在更新,并且您的 MyPages.tsx 看到该更新是 useEffect 以在更改时记录更改。

    useEffect(() => {
      console.log(response.newDate)
    }, [response]);
    

    如果你想在回调中访问最新的 redux 存储状态而完全没有任何时间问题,useStore 很有帮助,而且它根本不会导致重新渲染。

    const store = useStore();
    
    const callbackSuccessful = (data: IResponse) => {
        console.log("should be: " + data.newDate);
        console.log("Redux store: " + store.getState().apiResponse.newDate);
    };
    

    https://codesandbox.io/s/react-typescript-demo-pek65?file=/src/pages/MyPages.tsx

    【讨论】:

    • 感谢您的快速回复。我尝试了沙箱代码,我仍然在回调中变得陈旧。响应不是陈旧的:2020-04-30T04:55:49.604Z 应该是:2020-04-30T04:56:54.224Z
    • 我添加了 useLayoutEffect 和 useStore 作为选项
    【解决方案2】:

    使用 Zachary Haber 的useLayoutEffect 之前的答案是正确答案。

    但我可以分享两个低于标准的解决方案,它们都有自己的问题。

    解决方案 1

    在按钮上使用key 通知 React 它应该更新按钮对象的范围(即重新安装组件),因为它的一些依赖项已经更新。

    import React from "react";
    import { useResponse } from "../hooks/useResponse";
    import { IResponse } from "../utils/apiDef";
    
    const MyPages = () => {
        const { response, getNewDate } = useResponse();
      const callbackSuccessful = (data: IResponse) => {
        console.log("response is: " + response.newDate)
        console.log("callback data is: " + data.newDate)
      }
    
      const callbackFail = (data: any) => {
    
      }
    
      const handleButton = () => {
        getNewDate(callbackSuccessful,  callbackFail)
      }
      const buttonKey = response.newDate
        return <div>
        hello world {response.newDate}
        <br/>
        <button key={buttonKey} type="button" onClick={handleButton}>getNewDate</button>
      </div>;
    };
    
    export default MyPages;
    

    一个小问题:这将显示之前的结果,即response.newDate 将包含更改key 时的值。

    解决方案 2

    使用全局变量,例如state

    import React from "react";
    import { useResponse } from "../hooks/useResponse";
    import { IResponse } from "../utils/apiDef";
    
    const state = {
      response: undefined
    }
    const MyPages = () => {
      const { response, getNewDate } = useResponse();
      state.response = response;
      const callbackSuccessful = (data: IResponse) => {
        console.log("state response is: " + state.response.newDate)
        console.log("callback data is: " + data.newDate)
      }
    
      const callbackFail = (data: any) => {
    
      }
    
      const handleButton = () => {
        getNewDate(callbackSuccessful,  callbackFail)
      }
        return <div>
        hello world {response.newDate}
        <br/>
        <button type="button" onClick={handleButton}>getNewDate</button>
      </div>;
    };
    
    export default MyPages;
    

    在回调中,state.response.newDate 等于 data.newDate

    一个小问题:它不再是一个可重用的组件。只有在您的应用程序中有一个 MyPages 对象时,此解决方案才有效。所有实例都将指向同一个 static 全局变量,这将引入最后写入者获胜的竞争。

    你不应该这样做:

    <MyPages />
    <MyPages />
    

    这个解决方案的另一个问题:React 的优化;我不知道这会如何影响它。

    我希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2021-12-02
      • 1970-01-01
      • 1970-01-01
      • 2018-09-27
      • 2019-11-06
      • 1970-01-01
      • 1970-01-01
      • 2018-10-02
      相关资源
      最近更新 更多