React

2강 — state와 이벤트

슬라이드 보는 법

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

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

1강 복습

컴포넌트JSX를 return 하는 함수
props부모가 내려주는 값. 읽기 전용
map + key배열을 화면에 나열

오늘은 이 화면을 움직이게 만듭니다

오늘 끝나면 할 수 있는 것

  • 값이 바뀌면 화면이 따라 바뀌게 만든다
  • 클릭에 반응한다
  • 배열과 객체 state를 안전하게 바꾼다
  • 입력창을 다룬다
  • 여러 컴포넌트가 한 값을 함께 쓴다

오늘 배울 것

  • 7. state가 필요한 이유
  • 8. useState
  • 9. 이벤트
  • 10. 불변성
  • 11. 폼과 입력
  • 12. 상태 끌어올리기

7. state가 필요한 이유

그냥 변수로는 왜 안 되나

7. state가 필요한 이유

            
              function Counter() {
                let count = 0;

                return (
                  <button onClick={() => { count++; }}>
                    {count}
                  </button>
                );
              }
            
          

눌러도 계속 0

버튼을 누르면 숫자가 올라갈까요?

7. state가 필요한 이유

  • 변수는 바뀌었지만 React는 그 사실을 모른다
  • React는 다시 그려야 할 때만 다시 그린다
  • “이 값이 바뀌면 다시 그려라”고 알려줘야 한다

7. state가 필요한 이유

그 도구가 state

8. useState

값이 바뀌면 화면도 바뀌게 하려면

8. useState

          
            import { useState } from 'react';

            const [count, setCount] = useState(0);
            //     현재값   바꾸는 함수      처음값
          
        

8. useState

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

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

누르면 올라간다

8. useState js-2와 비교

DOM 조작

값 바꾸고
textContent 도 바꾼다

두 번 일한다
React

setCount 만 부른다

화면은 따라온다

8. useState 직접 대입 금지

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

              count = count + 1;   // 하면 안 된다
            
          
화면이 안 바뀐다
반드시 setCount 를 통해서

8. useState 함정

            
              setCount(count + 1);
              setCount(count + 1);
              setCount(count + 1);
            
          
예상3 증가
실제1 증가

여기서 set을 세 번 부르면 3이 올라갈까요?

8. useState 함수로 넘기기

            
              setCount((c) => c + 1);
              setCount((c) => c + 1);
              setCount((c) => c + 1);
            
          
실제3 증가

8. 정리

  • const [값, set값] = useState(초기값)
  • 바꿀 때는 반드시 set값()
  • set을 부르면 컴포넌트가 다시 실행된다
  • 이전 값이 필요하면 set값(c => ...)

9. 이벤트

사용자 동작에 반응하려면

9. 이벤트 이름

            
              <button onClick={handleClick}>누르기</button>
              <input onChange={handleChange} />
              <form onSubmit={handleSubmit}>
            
          
onclickonClick
onchangeonChange
onsubmitonSubmit

9. 이벤트 괄호

            
              {/* 함수를 넘김 */}
              <button onClick={handleClick}>

              {/* 즉시 실행됨 */}
              <button onClick={handleClick()}>
            
          
괄호를 붙이면
렌더링할 때 바로 실행된다

둘 중 어느 쪽이 맞을까요?

9. 이벤트 인자 넘기기

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

                return (
                  <>
                    <button onClick={() => setCount(c => c + 1)}>
                      +
                    </button>
                    <button onClick={() => setCount(c => c - 1)}>
                      -
                    </button>
                    <p>{count}번</p>
                  </>
                );
              }
            
          

3번

9. 정리

  • onClick 처럼 낙타등 표기
  • 값은 함수. 괄호를 붙이면 즉시 실행된다
  • 인자가 필요하면 () => 함수(인자)

10. 불변성

배열과 객체 state를 바꾸려면

10. 불변성 push 금지

            
              const [todos, setTodos] = useState([]);

              todos.push("우유 사기");   // 하면 안 된다
            
          
배열은 바뀌었지만
화면이 안 바뀐다

여기서 push를 쓰면 화면이 바뀔까요?

10. 불변성 새 배열

            
              setTodos([...todos, "우유 사기"]);
            
          
  • 우유 사기

10. 불변성 세 가지

            
              // 추가
              setTodos([...todos, 새항목]);

              // 삭제
              setTodos(todos.filter((t) => t.id !== id));

              // 수정
              setTodos(todos.map((t) =>
                t.id === id ? { ...t, done: true } : t
              ));
            
          
추가스프레드
삭제filter
수정map

10. 불변성 객체

            
              const [user, setUser] = useState({
                name: "홍길동", age: 20
              });

              setUser({ ...user, age: 21 });
            
          
name"홍길동"
age21

10. 정리

  • state는 고치지 말고 새로 만든다
  • push, splice 대신 스프레드
  • 추가는 [...], 삭제는 filter, 수정은 map

11. 폼과 입력

입력창의 값을 다루려면

11. 폼과 입력 제어 컴포넌트

            
              const [text, setText] = useState("");

              <input
                value={text}
                onChange={(e) => setText(e.target.value)}
              />
              <p>{text}</p>
            
          

안녕

11. 폼과 입력 함정

            
              <input value={text} />   {/* onChange 없음 */}
            
          
글자를 쳐도 아무것도 안 써진다
value가 state에 묶여 있기 때문

onChange를 빼면 글자가 써질까요?

11. 폼과 입력 submit

            
              function TodoForm({ onAdd }) {
                const [text, setText] = useState("");

                function handleSubmit(e) {
                  e.preventDefault();
                  onAdd(text);
                  setText("");
                }

                return <form onSubmit={handleSubmit}>...</form>;
              }
            
          

11. 정리

  • valueonChange항상 짝
  • 입력값은 e.target.value
  • submit에서는 e.preventDefault()

12. 상태 끌어올리기

여러 컴포넌트가 한 값을 함께 쓰려면

12. 상태 끌어올리기 문제

<App> ├─ <TodoForm> 새 할 일을 만든다 └─ <TodoList> 할 일을 보여준다

형제끼리는 값을 주고받을 수 없다

12. 상태 끌어올리기

둘의 공통 부모
state를 올린다

12. 상태 끌어올리기

            
              function App() {
                const [todos, setTodos] = useState([]);

                function addTodo(text) {
                  setTodos([...todos, { id: Date.now(), text }]);
                }

                return (
                  <>
                    <TodoForm onAdd={addTodo} />
                    <TodoList todos={todos} />
                  </>
                );
              }
            
          
  • 우유 사기

12. 정리

  • 값은 아래로 — props
  • 변경은 위로 — 함수를 props로 내려준다
  • 공유가 필요하면 공통 부모로 state를 올린다

정리

오늘 배운 것

한눈에

useState바뀌면 화면도 바뀌는 값
set 함수직접 대입 금지. 이전 값은 set(c => ...)
onClick함수를 넘긴다. 괄호 붙이면 즉시 실행
불변성고치지 말고 새로 만든다
value + onChange제어 컴포넌트
끌어올리기값은 아래로, 변경은 위로

실습

할 일 목록 만들기

실습 과제

  1. 입력창과 추가 버튼으로 할 일 추가
  2. 목록을 map 으로 그리기
  3. 각 항목에 삭제 버튼 (filter)
  4. 클릭하면 완료 표시 (map + 스프레드)

3~5강 내내 이 할 일 목록을 계속 고쳐 나갑니다

더 볼 것

3강에서는 바깥 세상과 이야기합니다