React

3강 — useEffect와 바깥 세상

슬라이드 보는 법

→ / Space다음으로
이전으로
↓ / ↑같은 주제 안에서 단계 이동
O전체 슬라이드 한눈에 보기
F전체화면

아래쪽 화살표가 보이면 그 주제는 단계별로 이어집니다

2강 복습

useState바뀌면 화면도 바뀌는 값
불변성고치지 말고 새로 만든다
끌어올리기값은 아래로, 변경은 위로

오늘은 React 바깥과 이야기합니다

오늘 끝나면 할 수 있는 것

  • 렌더링과 부수 효과를 구분한다
  • useEffect 의 의존성 배열을 이해한다
  • 무한 루프를 만들고, 고친다
  • 타이머를 정리한다
  • 서버에서 데이터를 가져온다

오늘 배울 것

  • 13. 렌더링과 부수 효과
  • 14. useEffect
  • 15. 의존성 배열
  • 16. 정리 함수
  • 17. 데이터 가져오기

13. 렌더링과 부수 효과

컴포넌트가 하면 안 되는 일

13. 렌더링과 부수 효과

컴포넌트의 일은
JSX를 돌려주는 것 하나뿐

같은 props와 state라면 항상 같은 결과여야 한다

13. 렌더링과 부수 효과 문제

            
              function Profile() {
                const [user, setUser] = useState(null);

                fetch("/api/user")          // 렌더링 중에 호출
                  .then((r) => r.json())
                  .then(setUser);

                return <p>{user?.name}</p>;
              }
            
          
setUser → 다시 렌더링
→ fetch → setUser → …

렌더링 중에 fetch를 부르면 어떻게 될까요?

13. 렌더링과 부수 효과

  • 서버 요청, 타이머, 직접 DOM 조작
  • 이런 것을 부수 효과라고 한다
  • 렌더링 중이 아니라 렌더링이 끝난 뒤에 해야 한다

14. useEffect

렌더링이 끝난 뒤에 실행하려면

14. useEffect

          
            import { useEffect } from 'react';

            useEffect(() => {
              // 렌더링이 끝난 뒤 실행할 코드
            }, [의존성]);
          
        

14. useEffect 빈 배열

            
              function App() {
                const [count, setCount] = useState(0);

                useEffect(() => {
                  console.log("실행됨");
                }, []);

                return <button onClick={() => setCount(count + 1)}>
                  {count}
                </button>;
              }
            
          
실행됨

14. 정리

  • 컴포넌트가 화면에 나타난 뒤에 실행
  • 서버 요청, 타이머 등록은 전부 여기서
  • 언제 다시 실행할지는 의존성 배열이 정한다

15. 의존성 배열

언제 다시 실행할지 정하려면

15. 의존성 배열 세 가지

[ ]처음 한 번만
[count]count가 바뀔 때마다
없음렌더링될 때마다 (매번)

15. 의존성 배열 [count]

            
              useEffect(() => {
                console.log("count:", count);
              }, [count]);
            
          
count: 0
count: 1
count: 2

15. 의존성 배열 배열 없음

            
              useEffect(() => {
                console.log("실행");
              });   // 배열이 없음
            
          
실행
실행
실행

15. 의존성 배열 무한 루프

            
              useEffect(() => {
                setCount(count + 1);
              });
            
          
setCount → 렌더링 → effect
→ setCount → 렌더링 → …
브라우저가 멈춘다

여기서 effect가 state를 바꾸면?

15. 의존성 배열 규칙

  • effect 안에서 바꾸는 값을 의존성에 넣으면 루프
  • 배열을 빼먹어도 루프
  • effect 안에서 쓰는 값은 전부 배열에 적는다

16. 정리 함수

벌인 일을 치우려면

16. 정리 함수 문제

            
              useEffect(() => {
                setInterval(() => {
                  console.log("1초");
                }, 1000);
              }, []);
            
          
화면을 떠나도 계속 돈다
타이머가 쌓인다

화면을 떠나면 이 타이머는 어떻게 될까요?

16. 정리 함수 return

            
              useEffect(() => {
                const timer = setInterval(() => {
                  console.log("1초");
                }, 1000);

                return () => clearInterval(timer);
              }, []);
            
          
화면을 떠나면
타이머도 함께 정리된다

16. 정리

  • 타이머, 이벤트 등록, 구독 — 치울 것이 있으면 return
  • 컴포넌트가 사라질 때 실행된다
  • 의존성이 바뀌어 다시 실행되기 직전에도 실행된다

17. 데이터 가져오기

서버에서 받아 화면에 그리려면

17. 데이터 가져오기

            
              const [users, setUsers] = useState([]);

              useEffect(() => {
                fetch("/api/users")
                  .then((r) => r.json())
                  .then(setUsers);
              }, []);
            
          
  • 홍길동
  • 윤경

17. 데이터 가져오기 async

            
              useEffect(() => {
                async function load() {
                  const r = await fetch("/api/users");
                  setUsers(await r.json());
                }
                load();
              }, []);
            
          
useEffect(async () => ...) 는
쓸 수 없다

17. 데이터 가져오기 세 가지 상태

            
              const [loading, setLoading] = useState(true);
              const [error, setError] = useState(null);

              // 로딩 중 / 실패 / 성공
              if (loading) return <p>불러오는 중…</p>;
              if (error) return <p>실패했습니다</p>;
              return <UserList users={users} />;
            
          

불러오는 중…

17. 정리

  • 요청은 useEffect(..., []) 안에서
  • effect에 async 를 직접 붙이지 않는다
  • 로딩 / 실패 / 성공 세 가지를 모두 만든다

정리

오늘 배운 것

한눈에

부수 효과화면 그리기 말고 딴 일
useEffect렌더링이 끝난 뒤 실행
[ ]처음 한 번만
[값]그 값이 바뀔 때마다
return () => {}정리 함수
로딩 / 실패 / 성공데이터는 항상 세 상태

실습

할 일 목록 이어가기

실습 과제

  1. 새로고침해도 할 일이 남아 있게 (localStorage + useEffect)
  2. 공개 API에서 목록을 받아와 화면에 그리기
  3. 로딩 중과 실패 화면 만들기

API는 jsonplaceholder.typicode.com 을 씁니다

더 볼 것

4강에서는 커진 앱을 정리합니다