source

React.useMemo를 사용한 비동기 호출

nicesource 2023. 3. 20. 23:20
반응형

React.useMemo를 사용한 비동기 호출

시나리오는 비교적 단순합니다.리모트 서버에서 장시간 실행되는 온디맨드 계산이 이루어집니다.우리는 결과를 메모하고 싶다.원격 리소스에서 동시에 가져오기는 하지만 이 계산 결과가 사용자에게 표시되기를 원할 뿐 모든 렌더에서 이 작업을 수행할 수는 없기 때문에 부작용이 아닙니다.

문제: React.useMemo는 Typescript의 비동기/대기 기능을 직접 지원하지 않으며 다음 약속을 반환합니다.

//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와의 약속을 사용해 왔지만, 이러한 상황에서는 여전히 어려움을 겪고 있습니다.

등의 만, 는 memoize-one이 인 것 .thisReact 함수 컴포넌트의 동작방식으로 인해 컨텍스트가 변경되면 메모화가 해제되므로 React.useMemo를 사용하려고 합니다.

아마도 나는 여기 둥근 구멍에 네모난 못을 끼워 넣으려고 하는 것 같다 - 만약 그렇다면 그것을 아는 것도 좋을 것이다.지금은 나만의 메모 기능을 사용할 수 있을 것 같습니다.

편집: memoize-one에서 다른 바보 같은 실수를 한 것도 한 부분이라고 생각합니다만, React.memo의 답을 알고 싶습니다.

여기 스니펫이 있습니다.메모화된 결과를 렌더링 방식으로 직접 사용하는 것이 아니라 계산 버튼 클릭 등 이벤트 주도의 방법으로 참조하는 것입니다.

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>);
}

비동기 콜이 종료되면 컴포넌트를 다시 렌더링합니다.메모화만으로는 그 달성에 도움이 되지 않습니다.대신 React 상태를 사용해야 합니다. 비동기 호출이 반환된 값을 유지하고 재렌더를 트리거할 수 있습니다.

하는 것은에, 내부도 아닙니다.useMemo(...)이치노 모든 은 내부에서 .useEffect.

완전한 솔루션은 다음과 같습니다.

const [result, setResult] = useState()

useEffect(() => {
  let active = true
  load()
  return () => { active = false }

  async function load() {
    setResult(undefined) // this is optional
    const res = await someLongRunningApi(arg1, arg2)
    if (!active) { return }
    setResult(res)
  }
}, [arg1, arg2])

에서는 비동기 함수로 .useEffect. 은 할 수 useEffect-를 async로 합니다.load리리리리리리리 리

한번 더 입니다.argchanges - 이 당신이 원하는 입니다. 꼭 해 두세요.argrender.: 더시시시시시 시시시 s s s s s 。setResult(undefined)는 옵션입니다.대신 다음 결과를 얻을 때까지 이전 결과를 화면에 유지할 수 있습니다. '어느 정도' 같은 걸할도 있어요.setLoading(true)사용자가 무슨 일이 일어나고 있는지 알 수 있도록 하겠습니다.

「」를 사용합니다.active깃발을 들다두은 첫 함수 콜이종료되기 될 수 .두 번째 비동기 함수 호출은 첫 번째 비동기 함수 호출이 종료되기 전에 종료될 수 있습니다.

  1. 첫 번째 콜을 시작하다
  2. 두 번째 콜을 시작하다
  3. 종료됩니다.「 」 。setResult()
  4. 번째 종료됩니다.「 」 、 「 」setResult(), , 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다.

컴포넌트가 일관성이 없는 상태가 됩니다.는 그것을 .useEffect를 리셋하기 기능. "를 .active 삭제:

  1. 설정하다active#1 = true 콜을
  2. 변경, arg " " " " " " , " " " "active#1 = false
  3. 설정하다active#2 = true 두 합니다.
  4. 종료됩니다.「 」 。setResult()
  5. 번째 종료됩니다.「 」 、 「 」setResult() 처음 있는 active#1false

편집: 아래 답변은 콜의 비동기 특성으로 인해 의도하지 않은 부작용이 있는 것 같습니다.대신 실제 계산을 서버에 메모하거나, 직접 작성한 닫힘을 사용하여 다음 중 하나를 확인하려고 합니다.arg변하지 않았어요. 않은 경우에도 할 수 있습니다.useEffect아래 설명과 같이

는 바로 그 점이라고 합니다.async함수는 항상 암묵적으로 약속을 반환합니다. 「」를 사용할 수 .await"CHANGE: "CHANGE: "CHANGE: " 。

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

여기서 코드 및 상자의 예를 참조하십시오.

, 패턴은, 을 활용하는 합니다.useEffect만, 이 경우는, 「」라고 하는 것은 「」라고 하는 것 .useMemo작동해야 합니다.

React는 useMemo를 비동기 API 호출과 같은 부작용 관리에 사용해서는 안 된다고 구체적으로 언급하고 있다고 생각합니다.관리 대상 장소:useEffect적절한 의존관계가 설정되어 있는 훅을 사용하여 재실행 여부를 판단합니다.

언급URL : https://stackoverflow.com/questions/61751728/asynchronous-calls-with-react-usememo

반응형