Skip to content
This page has been auto-translated and may contain errors.View in English

상태 끌어올리기

텍스트 입력 필드 옆에 입력된 내용을 표시하는 미리보기가 있습니다. 둘 다 같은 컴포넌트 트리에 있지만, 한 컴포넌트 안에서 선언한 상태는 이웃 컴포넌트에서 볼 수 없기 때문에 입력 필드와 미리보기 어느 쪽도 다른 쪽의 값을 읽거나 변경할 수 없습니다. 해결책은 그 상태를 둘이 공유하는 가장 가까운 컴포넌트로 옮긴 후, 각각에 props로 전달하는 것입니다. 이를 상태 끌어올리기라고 합니다.

다음은 한 값을 공유하는 두 컴포넌트입니다:

jsx
import { useState } from 'react'

function Form() {
  const [text, setText] = useState('')

  return (
    <>
      <TextInput text={text} onChange={setText} />
      <TextDisplay text={text} />
    </>
  )
}

function TextInput({ text, onChange }) {
  return <input value={text} onChange={e => onChange(e.target.value)} />
}

function TextDisplay({ text }) {
  return <p>You typed: {text}</p>
}

FormTextInputTextDisplay의 가장 가까운 공통 부모이므로, text는 여기에 있습니다. Formtext를 둘 다에게 전달하고, setTextonChange라는 이름으로 TextInput에 전달합니다. 누군가 입력하면 TextInput은 새 값을 가지고 onChange를 호출하고, Form의 상태가 업데이트되고, Form이 다시 렌더링됩니다. 그 다시 렌더링은 새로운 text를 두 자식 모두에게 다시 내려보내므로, TextDisplay는 자신의 상태를 유지하지 않으면서도 입력 필드의 내용을 정확히 표시합니다.

상태를 최대한 낮게 유지하기

상태 끌어올리기는 필요할 때만 하는 작업입니다. 핵심 원칙은 상태 공동 위치 배치입니다: 각 상태를 트리에서 최대한 낮게, 실제로 사용하는 컴포넌트 근처에 유지하고, 다른 무언가가 그 상태를 읽거나 변경해야 할 때만 끌어올립니다. 아무도 건드리지 않는 상태를 가진 컴포넌트는 그 상태를 자기 것으로 유지해야 합니다.

이것이 중요한 이유는 끌어올리는 데 비용이 들기 때문입니다. 상태가 올라갈 때마다 부모는 그것을 다시 props로 내려보내야 하고, 그 사이의 모든 컴포넌트는 그 값을 실제로 사용하지 않아도 그 props를 받아서 전달해야 합니다. 먼저 로컬로 시작하세요. 상태를 끌어올리는 것은 실제로 공유할 필요가 있는 가장 가까운 컴포넌트까지만 하고, 그 이상 올리지 마세요.

setter 전달하기

Formtext만 내려보내는 것이 아님을 주목하세요. setTextonChange props로 내려보냅니다. 이것이 상태 끌어올리기의 다른 절반입니다: 상태를 소유한 컴포넌트가 props를 통해 상태를 변경하는 방법을 제공하고, 자식이 값을 직접 관리하는 대신 그 함수를 호출합니다. TextInputsetText를 직접 보지 못합니다. 주어진 함수를 호출할 뿐, 그 함수가 실제로 무엇을 하는지는 부모가 결정합니다.

많은 깊이에 걸쳐 중첩된 컴포넌트 사이에 공유되는 상태의 경우, 각 계층을 통해 props를 전달하는 것은 더 이상 실용적이지 않습니다. React는 이 경우를 위한 도구들, Context를 포함하고 있으며, Hooks 챕터는 모든 컴포넌트를 통해 값을 연결하지 않고도 그 값을 읽는 hook인 useContext를 다룹니다. 그것은 이 챕터의 범위를 넘어갑니다. 위의 패턴이 먼저 사용해야 할 패턴입니다.

한 컴포넌트가 주어진 상태를 소유하도록 선택하고 그것을 그 값의 단일 출처로 취급합니다. 같은 데이터의 사본을 두 번째 컴포넌트의 자신의 상태에 유지하고 둘을 수동으로 동기화하려고 하지 마세요. 같은 값의 두 복사본은 한 가지 업데이트 경로라도 놓치는 순간 서로 다른 값이 되며, 그 버그를 쫓아다니는 것은 상태를 끌어올렸을 때의 추가 props보다 훨씬 더 나쁩니다. 이미 어딘가에 있는 상태에서 값을 유도할 수 있다면, 별도로 저장하는 대신 렌더링 중에 유도하세요.

주의해야 할 신호는 prop drilling입니다: 깊게 중첩된 하나의 소비자에게 도달하기 위해 여러 컴포넌트를 통해 전달되는 props인데, 그 사이의 모든 컴포넌트가 그것을 그냥 통과시킬 뿐 절대 사용하지 않는 경우입니다. 한두 계층 정도는 정상이며 이를 위해 재구조화할 필요가 없습니다. 많은 계층에 걸쳐 펼쳐지거나, 트리의 여러 관계없는 분기가 모두 같은 값이 필요할 때, 그것이 Context나 상태 관리 라이브러리가 가치를 발휘하는 때입니다. 상태 끌어올리기와 props 전달은 여전히 서로 가까운 컴포넌트가 공유하는 상태에 적합한 도구입니다. 그것 사이의 트리가 깊어지면 더 이상 올바른 도구가 아닙니다.

Juno공유 상태를 부모로 옮기기 두 컴포넌트가 같은 값이 필요할 때, 그 값을 어느 한 컴포넌트 대신 가장 가까운 공통 부모에게 주는 것이 핵심입니다. 그 부모가 상태를 유지하고, 값을 둘 다에게 전달하고, 자식이 변경을 요청할 수 있도록 함수를 전달합니다. 자식은 절대 값을 소유하지 않으며, 주어진 것을 사용하고 부모에게 업데이트를 요청합니다.
Juno공유 상태를 부모로 옮기기 두 컴포넌트가 상태를 공유해야 할 때는 가장 가까운 공통 부모로 끌어올리고, 값과 그 setter를 props로 전달하세요. 보통은 value props와 onChange 스타일의 콜백입니다. 그 외에는 상태를 최대한 로컬로 유지하세요. 공유할 필요가 있을 때만 끌어올리세요. 많은 중첩 컴포넌트에 걸쳐 공유되는 것의 경우 Context가 더 나은 도구이며, Hooks 챕터에서 어떻게 하는지 다룹니다.
Juno공유 상태를 부모로 옮기기 기본적으로 공동 위치의 상태를 사용하고, 가장 가까운 공유 소비자까지만 끌어올리며, 값과 그 setter를 props로 전달합니다. 컴포넌트 간에 복사본을 동기화하는 대신 각 값당 하나의 출처를 유지합니다. Prop drilling, 즉 그것을 사용하지 않는 계층을 통해 연결되는 props를 주의 깊게 보세요. 이것이 끌어올리기보다 Context나 저장소가 더 나은 맞춤인지의 신호입니다.

다음: Effects. 여기서는 렌더링 외부에서 일어나는 작업을 처리하기 위해 useEffect를 사용합니다.