분류 Reactjs

React useEffect : 모든 개발자가 알아야 할 4 가지 팁

컨텐츠 정보

  • 조회 292 (작성일 )

본문

React Hooks의 useEffects에 대해 이야기합시다! useEffect를 사용할 때 염두에 두어야 할 4 가지 팁을 알려 드리겠습니다.


https://medium.com/swlh/useeffect-4-tips-every-developer-should-know-54b188b14d9c


단일 용도로 useEffect 사용 


React Hooks에서는 여러 useEffect 함수를 가질 수 있습니다. 깨끗한 코드를 작성하는 방법을 분석하면 함수가 단일 목적 (문장이 하나의 아이디어 만 전달해야 하는 방식과 유사 함)을 제공해야 한다는 것을 알 수 있기 때문에 이것은 훌륭한 기능입니다.


useEffect를 짧고 유용한 단일 목적 함수로 분할하면 의도하지 않은 실행도 방지 됩니다 (종속성 배열을 사용할 때).


예를 들어, varB와 관련이 없는 varA가 있고 useEffect (setTimeout 사용)를 기반으로 재귀 카운터를 구축하려는 경우 잘못된 코드를 작성해 보겠습니다.


function App() {
const [varA, setVarA] = useState(0);
const [varB, setVarB] = useState(0);
// Don't do this!
useEffect(() => {
const timeoutA = setTimeout(() => setVarA(varA + 1), 1000);
const timeoutB = setTimeout(() => setVarB(varB + 2), 2000);
return () => {
clearTimeout(timeoutA);
clearTimeout(timeoutB);
};
}, [varA, varB]);
return (
<span>
Var A: {varA}, Var B: {varB}
</span>
);
}


보시다시피 varA 및 varB 변수 중 하나를 변경하면 두 변수 모두에서 업데이트가 트리거 됩니다. 이것이 이 후크가 제대로 작동하지 않는 이유입니다.


이것은 짧은 예이므로 당연하다고 느낄 수 있지만 더 많은 코드와 변수가 있는 더 긴 함수에서는 이것을 놓치게 될 것입니다. 그러니 옳은 일을 하고 useEffect를 분할하십시오.


이 경우 다음과 같아야 합니다.


function App() {
const [varA, setVarA] = useState(0);
const [varB, setVarB] = useState(0);
// Correct way
useEffect(() => {
const timeout = setTimeout(() => setVarA(varA + 1), 1000);
return () => clearTimeout(timeout);
}, [varA]);
useEffect(() => {
const timeout = setTimeout(() => setVarB(varB + 2), 2000);
return () => clearTimeout(timeout);
}, [varB]);
return (
<span>
Var A: {varA}, Var B: {varB}
</span>
);
}


참고 : 여기에 있는 코드는 예제 용일 뿐이며 useEffect의 문제를 쉽게 이해하는 데 도움이 됩니다. 일반적으로 변수가 이전 상태에 의존하는 경우 권장되는 방법은 대신 setVarA (varA => varA + 1)를 수행하는 것입니다. (이 메모를 추가하기 위해 나를 기억 해준 @Michael Landis에게 크레딧)


가능할 때마다 사용자 지정 후크 사용 


위의 예를 다시 보겠습니다. 변수 varA와 varB가 완전히 독립적이면 어떻게 됩니까?


이 경우 사용자 지정 후크를 만들어 각 변수를 분리 할 수 ​​있습니다. 이렇게 하면 각 함수가 어떤 변수에 대해 무엇을 하는지 정확히 알 수 있습니다.


그럼 커스텀 후크를 만들어 봅시다!


function App() {
const [varA, setVarA] = useVarA();
const [varB, setVarB] = useVarB();
return (
<span>
Var A: {varA}, Var B: {varB}
</span>
);
}
function useVarA() {
const [varA, setVarA] = useState(0);
useEffect(() => {
const timeout = setTimeout(() => setVarA(varA + 1), 1000);
return () => clearTimeout(timeout);
}, [varA]);
return [varA, setVarA];
}
function useVarB() {
const [varB, setVarB] = useState(0);
useEffect(() => {
const timeout = setTimeout(() => setVarB(varB + 2), 2000);
return () => clearTimeout(timeout);
}, [varB]);
return [varB, setVarB];
}


이제 각 변수에는 고유 한 후크가 있습니다. 훨씬 더 유지 보수가 쉽고 읽기 쉽습니다!


useEffect를 올바른 방식으로 조건부로 실행 


setTimeout 주제에 대해 다음 예제를 살펴 보겠습니다.


function App() {
const [varA, setVarA] = useState(0);
useEffect(() => {
const timeout = setTimeout(() => setVarA(varA + 1), 1000);
return () => clearTimeout(timeout);
}, [varA]);
return <span>Var A: {varA}</span>;
}


어떤 이유로 카운터를 최대 5 개로 제한하려고 합니다. 올바른 방법과 잘못된 방법이 있습니다.


먼저 잘못된 방법을 살펴 보겠습니다.


function App() {
const [varA, setVarA] = useState(0);
// Don't do this!
useEffect(() => {
let timeout;
if (varA < 5) {
timeout = setTimeout(() => setVarA(varA + 1), 1000);
}
return () => clearTimeout(timeout);
}, [varA]);
return <span>Var A: {varA}</span>;
}



이 방법이 작동하지만, clearTimeout은 varA 변경시 실행되는 반면 setTimeout은 조건부로 실행된다는 점을 명심하십시오.


useEffect를 조건부로 실행하는 권장 방법은 다음과 같이 함수 시작 부분에 조건부 반환을 수행하는 것입니다.


function App() {
const [varA, setVarA] = useState(0);
useEffect(() => {
if (varA >= 5) return;
const timeout = setTimeout(() => setVarA(varA + 1), 1000);
return () => clearTimeout(timeout);
}, [varA]);
return <span>Var A: {varA}</span>;
}


이것이 머티리얼 UI가 사용하는 것 (다른 많은 것뿐만 아니라)을 보고 실수로 useEffect를 실행하지 않도록 합니다.


종속성 배열의 useEffect 안에 있는 모든 소품을 입력합니다. 


ESLint를 사용하는 경우 ESLint 전체 딥 규칙에서 오는 경고를 보았을 것입니다.


이것은 매우 중요합니다. 앱이 점점 커지면 각 useEffect에 더 많은 종속성 (props)이 추가됩니다. 이들을 모두 추적하고 오래된 폐쇄를 방지하려면 모든 종속성을 종속성 배열에 추가해야 합니다. (이 주제에 대한 공식적인 견해는 다음과 같습니다.)


다시 한 번, setTimeout 주제에 대해 이전 예제와 마찬가지로 setTimeout을 한 번만 실행하고 varA에 추가하려고 한다고 가정 해 보겠습니다.


다음과 같은 잘못된 예를 사용하고 싶을 수 있습니다.


function App() {
const [varA, setVarA] = useState(0);
useEffect(() => {
const timeout = setTimeout(() => setVarA(varA + 1), 1000);
return () => clearTimeout(timeout);
}, []); // Avoid this: varA is not in the dependency array!
return <span>Var A: {varA}</span>;
}


이 방법으로 원하는 작업을 수행 할 수 있지만 잠시 시간을 내어 "코드가 커지면 어떻게 됩니까?"또는 "위의 코드를 다른 것으로 변경하려면 어떻게 해야합니까?"라고 생각해 보겠습니다.


이 경우 발생할 수 있는 문제 (예 : 오래된 소품 및 클로저)를 테스트하고 감지하는 것이 훨씬 쉬워 지므로 변수를 모두 매핑하고 싶을 것입니다.


올바른 방법은 다음과 같습니다.


function App() {
const [varA, setVarA] = useState(0);
useEffect(() => {
if (varA > 0) return;
const timeout = setTimeout(() => setVarA(varA + 1), 1000);
return () => clearTimeout(timeout);
}, [varA]); // Great, we have our dependency array correctly set
return <span>Var A: {varA}</span>;
}


그게 다예요. 질문이나 제안이 있으면 모두 귀입니다! 아래에 답장하거나 댓글을 남겨 주시면 꼭 확인해보세요!