使用React.useMemo进行异步调用 [英] Asynchronous calls with React.useMemo

查看:480
本文介绍了使用React.useMemo进行异步调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

场景相对简单:我们在远程服务器上进行了长时间运行的按需计算.我们要记住结果.即使我们是从远程资源异步获取的,这也不是副作用,因为我们只是希望将计算结果显示给用户,并且我们绝对不想在每个渲染器上都这样做.

Scenario is relatively simple: we have a long-running, on-demand calculation that occurs on a remote server. We want to memoize the result. Even though we are fetching asychronously from a remote resource, this isn't a side effect because we just want the result of this calculation to display to the user and we definitely don't want to do this on every render.

问题:React.useMemo似乎不直接支持Typescript的async/await并会返回一个Promise:

Problem: it seems that React.useMemo does not directly support Typescript's async/await and will return a promise:

//returns a promise: 
let myMemoizedResult = React.useMemo(() => myLongAsyncFunction(args), [args])
//also returns a promise:
let myMemoizedResult = React.useMemo(() => (async () => await myLongAsyncFunction(args)), [args])

等待异步函数结果并使用React.useMemo记住结果的正确方法是什么?我在纯JS中使用了常规的Promise,但在这类情况下仍然难以解决.

What is the correct way to wait on the result from an asynchronous function and memoize the result using React.useMemo? I've used regular promises with plain JS but still struggle with them in these types of situations.

我尝试了其他方法,例如备忘一,但问题似乎是 this 上下文因React函数组件的工作方式而改变

I've tried other approaches such as memoize-one, but the issue seems to be that the this context changes due to the way that React function components work break the memoization, which is why I'm trying to use React.useMemo.

也许我正试图在此处将方钉固定在一个圆孔中-如果是这种情况,也应该知道这一点.现在,我可能只打算使用自己的记忆功能.

Maybe I'm trying to fit a square peg in a round hole here - if that's the case it would be good to know that too. For now I'm probably just going to roll my own memoizing function.

我认为部分原因是我在备忘录1中犯了一个不同的愚蠢错误,但是我仍然很想知道React.memo的答案.

I think part of it was that I was making a different silly mistake with memoize-one, but I'm still interested to know the answer here wrt React.memo.

这是一个摘要-想法不是直接在render方法中使用记录的结果,而是以事件驱动的方式(例如,在计算"按钮上单击)进行引用.

Here's a snippet - the idea is not to use the memoized result directly in the render method, but rather as something to reference in an event-driven way i.e. on a Calculate button click.

export const MyComponent: React.FC = () => {
    let [arg, setArg] = React.useState('100');
    let [result, setResult] = React.useState('Not yet calculated');

    //My hang up at the moment is that myExpensiveResultObject is 
    //Promise<T> rather than T
    let myExpensiveResultObject = React.useMemo(
        async () => await SomeLongRunningApi(arg),
        [arg]
    );

    const getResult = () => {
        setResult(myExpensiveResultObject.interestingProperty);
    }

    return (
        <div>
            <p>Get your result:</p>
            <input value={arg} onChange={e => setArg(e.target.value)}></input>
            <button onClick={getResult}>Calculate</button>
            <p>{`Result is ${result}`}</p>
        </div>);
}

推荐答案

编辑:由于调用的异步性质,下面的原始答案似乎有一些意外的副作用.相反,我会尝试考虑在服务器上存储实际的计算,或者使用自写的闭包来检查 arg 是否未更改.否则,您仍然可以使用如下所述的 useEffect 之类的东西.

My original answer below seems to have some unintended side effects due to the asynchronous nature of the call. I would instead try and either think about memoizing the actual computation on the server, or using a self-written closure to check if the arg hasn't changed. Otherwise you can still utilize something like useEffect as I described below.

我相信问题在于 async 函数总是隐式返回一个promise.既然是这种情况,您可以直接等待结果以解开承诺:

I believe the problem is that async functions always implicitly return a promise. Since this is the case, you can directly await the result to unwrap the promise:

const getResult = async () => {
  const result = await myExpensiveResultObject;
  setResult(result.interestingProperty);
};

示例代码框此处.

我确实认为,更好的模式可能是利用 useEffect ,它依赖于某些状态对象,在这种情况下,该状态对象仅在单击按钮时设置,但似乎 useMemo 应该也可以.

I do think though that a better pattern may be to utilize a useEffect that has a dependency on some state object that only gets set on the button click in this case, but it seems like the useMemo should work as well.

这篇关于使用React.useMemo进行异步调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆