한 걸음씩

[React] Effects and Data Fetching 본문

React

[React] Effects and Data Fetching

winter17 2024. 1. 27. 10:19

 

 

 

3개의 useEffect와 console.log로 출력했을 때 무엇이 먼저 동작할까에 대한 과정

react의 useEffect 훅은 컴포넌트의 라이프사이클에서 특정 시점에 실행되도록 하는데, 다양한 상황에서 동작할 수 있다.

 

console.log('During render')
  • 매 렌더링 시에 출력된다.
useEffect(function(){
    console.log("After initial render")
}, [])
  • 초기 렌더링 시에만 실행
useEffect(function(){
    console.log("After every render")
})
  • 초기 렌더링과 매 렌더링 시에 실행된다.
useEffect(function(){
    console.log("d")
}, [query])
  • query 값이 변경될 때마다 실행된다.

 

useEffect 훅 내부에서 return 이후에 작성되는 것은 clean up 하기 위함이다. 

컴포넌트가 언마운트되거나 업데이트되기 전에 필요한 정리 작업을 수행할 수 있다.

일반적으로 useEffect의 클리너 함수는 다음 렌더링이 진행되기 전에 호출되며, 여기에서 이전에 등록한 효과를 정리하거나 지원을 해제하는 등의 작업을 수행할 수 있다. 이는 메모리 누수를 방지하고 애플리케이션 성능을 최적화하는 데 도움이 된다.  


# challenge: Currency Converter

초기상태

 

입력값이 100이고 아무것도 설정하지 않은 상태

 

같은 나라를 선택했을 때

 

export default function App() {
  const [amount, setAmount] = useState(1);
  const [fromCur, setFromCur] = useState("EUR");
  const [toCur, setToCur] = useState("USD");
  const [converted, setConverted] = useState("");
  const [isLoading, setIsLoading] = useState(false);
  useEffect(
    function () {
      async function convert() {
        // 로딩상태가 api를 불러오기 전후에 따라 참 거짓으로 바뀔 수 있도록 지정
        setIsLoading(true);
        const res = await fetch(
          `https://api.frankfurter.app/latest?amount=${amount}&from=${fromCur}&to=${toCur}`
        );
        const data = await res.json();
        setConverted(data.rates[toCur]);
        setIsLoading(false);
      }
      // 불필요한 api 호출을 막기 위함
      if (fromCur === toCur) return setConverted(amount);
      convert();
    },
    // 의존성 배열에 amount, fromCur, toCur를 넣은 이유: 
    // 초기상태에서 값을 입력하고 아무것도 select하지 않았을 때 값을 업데이트 하기 위함
    [amount, fromCur, toCur]
  );
  
  return (
    <div>
      <input
        type="text"
        value={amount}
        // e.target.value는 문자열이기 때문에 숫자형으로 변환 필요
        onChange={(e) => setAmount(Number(e.target.value))}
        disabled={isLoading}
      />
      <select
        value={fromCur}
        onChange={(e) => setFromCur(e.target.value)}
        disabled={isLoading}
      >
        <option value="USD">USD</option>
        <option value="EUR">EUR</option>
        <option value="CAD">CAD</option>
        <option value="INR">INR</option>
      </select>
      <select
        value={toCur}
        onChange={(e) => setToCur(e.target.value)}
        disabled={isLoading}
      >
        <option value="USD">USD</option>
        <option value="EUR">EUR</option>
        <option value="CAD">CAD</option>
        <option value="INR">INR</option>
      </select>
      <p>
        {converted} {toCur}
      </p>
    </div>
  );
}