Post

리액트 state 보존과 초기화

✨리액트 state

리액트는 UI 트리를 통해 각 state가 어떤 컴포넌트에 속해있는지 위치를 파악합니다. 위치를 파악하고, state를 보존할지 초기화할지 결정합니다.

📘같은 위치의 “같은” 컴포넌트는 state를 보존

JSX마크업에서의 위치가 아닌 UI트리에서의 위치가 같은 컴포넌트는 state를 보존

예시

See the Pen 같은 위치의 같은 컴포넌트는 state를 보존 by 혬 (@jexbagvl-the-reactor) on CodePen.

체크박스를 선택하거나 해제할 때 카운터 state는 보존됩니다.

<Counter /> 컴포넌트는 root인 App 컴포넌트가 반환한 div의 첫번째 자식이기 때문입니다. https://ko.react.dev/_next/image?url=%2Fimages%2Fdocs%2Fdiagrams%2Fpreserving_state_same_component.png&w=640&q=75

즉, 같은 위치에 있고 같은 컴포넌트이기 때문에 state를 초기화하지 않습니다.

📘같은 위치의 “다른” 컴포넌트는 state를 초기화

See the Pen 같은 위치의 다른 컴포넌트는 초기화 by 혬 (@jexbagvl-the-reactor) on CodePen.

체크박스를 선택 유무에 따라 root의 App 컴포넌트의 첫번째 자식요소는 <Counter /> 또는 <p></p>태그로 변경됩니다.

1. take a break 체크박스를 선택하면, <Counter />에서 <p> 태그로 자식 요소가 변경됩니다.

https://ko.react.dev/_next/image?url=%2Fimages%2Fdocs%2Fdiagrams%2Fpreserving_state_diff_pt1.png&w=828&q=75

2. take a break 체크박스의 선택이 해제되면, <p> 태그에서 <Counter />로 자식 요소가 변경됩니다.

https://ko.react.dev/_next/image?url=%2Fimages%2Fdocs%2Fdiagrams%2Fpreserving_state_diff_pt2.png&w=828&q=75

<p> 태그<Counter />는 같은 위치에 존재하지만, 조건에 따라 서로 다른 컴포넌트를 렌더링을합니다.
같은 위치의 다른 컴포넌트를 렌더링할 때, 컴포넌트는 state를 초기화하기때문에 count 값이 초기화가 됩니다.

✨챌린지

💻입력 문자열이 사라지는 것 고치기

이 예시에서 버튼을 누르면 메시지를 보여줍니다. 하지만 버튼을 누르는 것은 또한 원치 않게 state를 초기화합니다. 왜 이런 현상이 일어날까요? 버튼을 눌러도 입력 문자열이 초기화되지 않도록 고쳐보세요.

예시코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import { useState } from "react";

export default function App() {
  const [showHint, setShowHint] = useState(false);
  if (showHint) {
    return (
      <div>
        <p>
          <i>Hint: Your favorite city?</i>
        </p>
        <Form />
        <button
          onClick={() => {
            setShowHint(false);
          }}
        >
          Hide hint
        </button>
      </div>
    );
  }
  return (
    <div>
      <Form />
      <button
        onClick={() => {
          setShowHint(true);
        }}
      >
        Show hint
      </button>
    </div>
  );
}

function Form() {
  const [text, setText] = useState("");
  return <textarea value={text} onChange={(e) => setText(e.target.value)} />;
}

📖해결

  • 원인: Form이 다른 위치에서 렌더링되기 때문에 문제가 발생
  • Form을 같은 자리에서 렌더링되도록 하기

See the Pen 입력 문자열 사라지는 것 고치기 by 혬 (@jexbagvl-the-reactor) on CodePen.

💻두 필드를 맞바꾸기

다음 폼은 first name과 last name을 입력받습니다. 또한 어떤 필드가 앞에 가는지를 조절하는 체크 박스로 있습니다. 체크 박스를 선택하면 “Last name” 필드가 “First name” 필드 앞에 나타납니다.

거의 모든 작업에는 버그가 있습니다. “First name”에 입력을 하고 체크 박스를 선택해도 문자열은 “Last name”이 된 첫 번째 인풋에 그대로 있습니다. 순서를 바꿀 때 입력 문자열도 이동하도록 수정해보세요.

예시코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import { useState } from "react";

export default function App() {
  const [reverse, setReverse] = useState(false);
  let checkbox = (
    <label>
      <input
        type="checkbox"
        checked={reverse}
        onChange={(e) => setReverse(e.target.checked)}
      />
      Reverse order
    </label>
  );
  if (reverse) {
    return (
      <>
        <Field label="Last name" />
        <Field label="First name" />
        {checkbox}
      </>
    );
  } else {
    return (
      <>
        <Field label="First name" />
        <Field label="Last name" />
        {checkbox}
      </>
    );
  }
}

function Field({ label }) {
  const [text, setText] = useState("");
  return (
    <label>
      {label}:{" "}
      <input
        type="text"
        value={text}
        placeholder={label}
        onChange={(e) => setText(e.target.value)}
      />
    </label>
  );
}

📖해결

  • 원인: state는 트리 위치로 컴포넌트와 연결하기 때문에, 순서가 바뀌어도 state 값이 변경되지 않은 것
  • key를 사용해서 해당 input의 값 저장하기

See the Pen 두 필드 맞바꾸기 by 혬 (@jexbagvl-the-reactor) on CodePen.

참고 사이트

This post is licensed under CC BY 4.0 by the author.