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이 인 것 .this
React 함수 컴포넌트의 동작방식으로 인해 컨텍스트가 변경되면 메모화가 해제되므로 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
리리리리리리리 리
한번 더 입니다.arg
changes - 이 당신이 원하는 입니다. 꼭 해 두세요.arg
render.: 더시시시시시 시시시 s s s s s 。setResult(undefined)
는 옵션입니다.대신 다음 결과를 얻을 때까지 이전 결과를 화면에 유지할 수 있습니다. '어느 정도' 같은 걸할도 있어요.setLoading(true)
사용자가 무슨 일이 일어나고 있는지 알 수 있도록 하겠습니다.
「」를 사용합니다.active
깃발을 들다두은 첫 함수 콜이종료되기 될 수 .두 번째 비동기 함수 호출은 첫 번째 비동기 함수 호출이 종료되기 전에 종료될 수 있습니다.
- 첫 번째 콜을 시작하다
- 두 번째 콜을 시작하다
- 종료됩니다.「 」 。
setResult()
- 번째 종료됩니다.「 」 、 「 」
setResult()
, , 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다, 틀렸다.
컴포넌트가 일관성이 없는 상태가 됩니다.는 그것을 .useEffect
를 리셋하기 기능. "를 .active
삭제:
- 설정하다
active#1 = true
콜을 - 변경, arg " " " " " " , " " " "
active#1 = false
- 설정하다
active#2 = true
두 합니다. - 종료됩니다.「 」 。
setResult()
- 번째 종료됩니다.「 」 、 「 」
setResult()
처음 있는active#1
false
편집: 아래 답변은 콜의 비동기 특성으로 인해 의도하지 않은 부작용이 있는 것 같습니다.대신 실제 계산을 서버에 메모하거나, 직접 작성한 닫힘을 사용하여 다음 중 하나를 확인하려고 합니다.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
'source' 카테고리의 다른 글
경고:목록의 각 아이는 고유한 "키" 소품을 가지고 있어야 합니다. (0) | 2023.03.20 |
---|---|
Safari 11.1: ajax/X입력[type=file]이(가) 비어 있으면 HR 양식 제출이 실패함 (0) | 2023.03.20 |
워드프레스:기본 메뉴 항목에 URL GET 매개 변수를 추가하려면 어떻게 해야 합니까? (0) | 2023.03.20 |
문자열이 유효한 JSON인지 확인하는 방법 (0) | 2023.03.20 |
파워 쿼리를 사용하여 뛰어난 성능을 발휘하는 Json (0) | 2023.03.20 |