React Hooks로 데이터를 가져올 때 경쟁 조건 방지
15628 단어 reactwebdevhooksjavascript
useEffect
후크는 기능 구성 요소에서 부작용을 수행하는 데 적합합니다. 이에 대한 한 가지 일반적인 예는 데이터를 가져오는 것입니다. 그러나 효과를 정리하는 데 주의를 기울이지 않으면 경쟁 조건이 발생할 수 있습니다! 이 게시물에서는 이러한 경쟁 조건 문제가 발생하지 않도록 효과를 적절하게 정리할 것입니다.설정
예제 앱에서는 이름을 클릭하면 사람들의 프로필 데이터를 가짜로 로드할 것입니다. 경합 상태를 시각화하는 데 도움이 되도록 0초에서 5초 사이의 임의 지연을 구현하는
fakeFetch
함수를 만듭니다.const fakeFetch = person => {
return new Promise(res => {
setTimeout(() => res(`${person}'s data`), Math.random() * 5000);
});
};
초기 구현
초기 구현에서는 단추를 사용하여 현재 프로필을 설정합니다. 다음 상태를 유지하면서 이를 구현하기 위해
useState
후크에 도달합니다.person
, 사용자가 선택한 인물data
, 선택한 사람loading
, 데이터가 현재 로드되고 있는지 여부useEffect
가 변경될 때마다 가짜 가져오기를 수행하는 person
후크를 추가로 사용합니다.import React, { Fragment, useState, useEffect } from 'react';
const fakeFetch = person => {
return new Promise(res => {
setTimeout(() => res(`${person}'s data`), Math.random() * 5000);
});
};
const App = () => {
const [data, setData] = useState('');
const [loading, setLoading] = useState(false);
const [person, setPerson] = useState(null);
useEffect(() => {
setLoading(true);
fakeFetch(person).then(data => {
setData(data);
setLoading(false);
});
}, [person]);
return (
<Fragment>
<button onClick={() => setPerson('Nick')}>Nick's Profile</button>
<button onClick={() => setPerson('Deb')}>Deb's Profile</button>
<button onClick={() => setPerson('Joe')}>Joe's Profile</button>
{person && (
<Fragment>
<h1>{person}</h1>
<p>{loading ? 'Loading...' : data}</p>
</Fragment>
)}
</Fragment>
);
};
export default App;
앱을 실행하고 버튼 중 하나를 클릭하면 가짜 가져오기가 예상대로 데이터를 로드합니다.
경쟁 조건에 도달
문제는 사람들 사이를 빠르게 전환하기 시작할 때 발생합니다. 가짜 가져오기에 임의의 지연이 있다는 사실을 감안할 때 가져오기 결과가 잘못된 순서로 반환될 수 있음을 곧 알게 됩니다. 또한 선택한 프로필과 로드된 데이터가 동기화되지 않을 수 있습니다. 나쁜 표정이야!
여기서 일어나는 일은 상대적으로 직관적입니다.
setData(data)
후크 내의 useEffect
는 fakeFetch
약속이 해결된 후에만 호출됩니다. 실제로 어떤 버튼이 마지막으로 호출되었는지에 관계없이 어떤 약속이 마지막으로 해결되든 마지막으로 setData
를 호출합니다.이전 가져오기 취소
가장 최근이 아닌 클릭에 대한 호출
setData
을 "취소"하여 이 경합 상태를 수정할 수 있습니다. useEffect
후크 내에서 범위가 지정된 부울 변수를 만들고 이 부울 "취소된"변수를 useEffect
로 설정하는 정리 함수를 true
후크에서 반환하여 이를 수행합니다. 약속이 확인되면 "취소된"변수가 false인 경우에만 setData
가 호출됩니다.해당 설명이 다소 혼란스럽다면
useEffect
후크의 다음 코드 샘플이 도움이 될 것입니다.useEffect(() => {
let canceled = false;
setLoading(true);
fakeFetch(person).then(data => {
if (!canceled) {
setData(data);
setLoading(false);
}
});
return () => (canceled = true);
}, [person]);
이전 버튼 클릭의
fakeFetch
약속이 나중에 확인되더라도 해당 canceled
변수는 true
로 설정되고 setData(data)
는 실행되지 않습니다!새로운 앱이 어떻게 작동하는지 살펴보겠습니다.
완벽함 - 다른 버튼을 몇 번 클릭하더라도 항상 마지막 버튼 클릭과 관련된 데이터만 표시됩니다.
전체 코드
이 블로그 게시물의 전체 코드는 아래에서 찾을 수 있습니다.
import React, { Fragment, useState, useEffect } from 'react';
const fakeFetch = person => {
return new Promise(res => {
setTimeout(() => res(`${person}'s data`), Math.random() * 5000);
});
};
const App = () => {
const [data, setData] = useState('');
const [loading, setLoading] = useState(false);
const [person, setPerson] = useState(null);
useEffect(() => {
let canceled = false;
setLoading(true);
fakeFetch(person).then(data => {
if (!canceled) {
setData(data);
setLoading(false);
}
});
return () => (canceled = true);
}, [person]);
return (
<Fragment>
<button onClick={() => setPerson('Nick')}>Nick's Profile</button>
<button onClick={() => setPerson('Deb')}>Deb's Profile</button>
<button onClick={() => setPerson('Joe')}>Joe's Profile</button>
{person && (
<Fragment>
<h1>{person}</h1>
<p>{loading ? 'Loading...' : data}</p>
</Fragment>
)}
</Fragment>
);
};
export default App;
Reference
이 문제에 관하여(React Hooks로 데이터를 가져올 때 경쟁 조건 방지), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/nas5w/avoiding-race-conditions-when-fetching-data-with-react-hooks-4pi9텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)