为什么我无法通过 React 中的 ref 存储的解析函数解析 Promise?

问题描述 投票:0回答:1

我正在尝试创建一个 promisify 风格的钩子,其想法是最终将其与 Redux Toolkit 一起使用,以允许使用新的 React 19

use
钩子。

这是这个东西如何工作的原理:

function usePromise(input: {
    isLoading: true,
    data: null
} | {
    isLoading: false,
    data: string;
}) {


    // Store the resolve function in a ref 
    const resRef = useRef<(data: string) => void>(null);

    // Create a new promise 
    // Store the resolve function in the ref 
    const promiseRef = useRef(
        new Promise((res) => {
            resRef.current = res;

            //res("xxx") // 👈 this will resolve though
        })
    );

    // When input changes, if there is data, resolve the promise
    useEffect(() => {
        if (!input.isLoading) {
            resRef.current?.(input.data);
        }

    }, [input]);

    // Return the promise 
    return promiseRef.current;
}

用法如下:

export function MyComponent() {

    const [value, setValue] = useState<null | string>(null);

    const prom = usePromise(value ? {
        isLoading: false,
        data: value
    } : {
        isLoading: true,
        data: null
    });

    prom.then((v) => alert(v))

    return <div >

        <button onClick={() => setValue("123")}>Click me</button>
    </div>
}

在这里,我希望当我们单击按钮时,承诺将得到解决,并且我们会看到警报。然而,事实并非如此。

这是怎么回事?

我在这里复制了这个问题:https://github.com/dwjohnston/react-promise-issue

reactjs
1个回答
0
投票

您的问题是,每次钩子运行时您都会创建一个新的 Promise,并将

resRef.current
设置为最后一个 Promise 的解析器函数。然而,只有传递到
useRef
钩子的第一个承诺才会存储在
promiseRef.current
中。

要解决此问题,避免重新创建承诺

function usePromise(input) {
    const resRef = useRef();
    const promiseRef = useRef();
    if (!promiseRef.current) {
        promiseRef.current = new Promise(resolve => {
            resRef.current = resolve;
        });
    }

    useEffect(() => {
        if (!input.isLoading) {
            resRef.current(input.data);
        }
    }, [input]);
    return promiseRef.current;
}
© www.soinside.com 2019 - 2024. All rights reserved.