분류 Reactjs

React에 대한 완전한 소개(6)

컨텐츠 정보

  • 조회 275 (작성일 )

본문

상태 읽기 및 업데이트 


상태 업데이트를 추적하고 가상 DOM 확산 및 실제 DOM 조정을 트리거 하려면 React는 구성 요소 내에서 사용되는 모든 상태 요소에 대한 변경 사항을 알고 있어야 합니다. 효율적인 방식으로 이를 수행하려면 React는 컴포넌트에 도입 한 각 상태 요소에 대해 특수 getter 및 setter를 사용해야 합니다. 여기서 useState 후크가 작동합니다. 그것은 상태 요소를 정의하고 getter와 setter를 돌려줍니다!


구현하려는 카운트 상태 요소에 필요한 것은 다음과 같습니다.

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

useState 함수는 정확히 2 개의 항목이 있는 배열을 반환합니다. 첫 번째 항목은 값 (getter)이고 두 번째 항목은 함수 (setter)입니다. 이 항목 이름을 지정하기 위해 배열 소멸을 사용했습니다. 원하는 이름을 지정할 수 있지만 [name, setName]이 규칙입니다.


첫 번째 항목 "value"는 문자열, 숫자, 배열 또는 기타 유형일 수 있습니다. 이 경우에는 숫자가 필요했고 그 숫자를 0으로 초기화해야 했습니다. React.useState의 인수는 상태 요소의 초기 값으로 사용됩니다.


두 번째 항목 "function"은 호출 될 때 state 요소의 값을 변경합니다 (필요한 경우 DOM 처리를 트리거 함). setCount 함수가 호출 될 때마다 React는 Button 구성 요소를 다시 렌더링하여 구성 요소에 정의 된 모든 변수 (카운트 값 포함)를 새로 고칩니다. setCount에 전달하는 인수는 count의 새로운 값이 됩니다.


버튼의 레이블을 증가 시키기 위해 해야 ​​할 일은 onClick 이벤트 내에서 setCount 함수를 호출하고 현재 카운트 값을 1 씩 증가 시키는 것입니다. 레이블 증가 버튼 예제의 전체 코드는 다음과 같습니다.

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

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

ReactDOM.render(<Button />, mountNode);

계속해서 테스트 해보십시오. 버튼은 이제 클릭 할 때마다 레이블을 증가시킵니다.


UI 자체를 변경하기 위한 조치를 구현하지 않은 방법에 주목하십시오. 대신, 우리는 메모리에서 JavaScript 객체를 변경하는 액션을 구현했습니다! 우리의 UI 구현은 기본적으로 React에 버튼의 레이블이 항상 count 객체의 값을 반영하기를 원한다고 알려주었습니다. 우리 코드는 DOM 업데이트를 수행하지 않았습니다. 


const 키워드를 사용하여 변경되는 값이지만 카운트를 정의하는 방법에 주목하십시오! 우리의 코드는 그 값을 바꾸지 않을 것입니다. React는 새로운 Button 함수 호출을 사용하여 새로운 상태의 UI를 렌더링합니다. 새로운 호출에서 useState 함수 호출은 새로운 새로운 카운트 값을 제공합니다.


useState 함수는 놀이터에서 전 세계적으로 사용 가능합니다. 이것은 React.useState의 별명 일 뿐입니다. 코드에서 명명된 가져 오기를 사용하여 모듈 범위에서 useState를 직접 사용할 수 있습니다. 


import React, { useState } from 'react';


이 힘을 높이려면 몇 가지 예가 더 필요합니다. 이 기본 예제에 더 많은 기능을 추가하겠습니다. 버튼이 많고 모두 하나의 공유 카운트 값을 늘리도록 합시다.


여러 컴포넌트로 작업 


지금까지 가지고 있는 Button 구성 요소를 두 가지 구성 요소로 나누겠습니다.

  • 버튼 요소를 나타내지 만 정적 레이블이 있는 Button 구성 요소를 유지하십시오.
  • 카운트 값을 표시하려면 새 디스플레이 구성 요소를 추가하십시오.

새로운 디스플레이 구성 요소는 상태 나 상호 작용이 없는 순수한 프리젠테이션 구성 요소입니다. 그건 정상입니다 모든 React 컴포넌트가 상태 저장 후크를 갖거나 대화식 이어야 하는 것은 아닙니다.

const Display = (props) => (
  <pre>COUNT VALUE HERE...</pre>
);


디스플레이 구성 요소의 책임은 단순히 소품으로 받을 값을 표시하는 것입니다. 예를 들어, 사전 요소가 값을 호스팅 하는 데 사용되었다는 사실이 그 책임의 일부입니다. 이 응용 프로그램의 다른 구성 요소는 그것에 대해 아무 말도 하지 않습니다!


형제 구성 요소 렌더링 


이제 렌더링 할 버튼과 디스플레이라는 두 가지 요소가 있습니다. 다음과 같이 서로 바로 옆에 렌더링 할 수 없습니다.

// This will not work

ReactDOM.render(<Button /><Display />, mountNode);


JSX가 변환 될 때 각 요소가 함수 호출로 변환되므로 React에서 이와 같은 인접 요소를 렌더링 할 수 없습니다. 이 문제를 처리 할 수 있는 몇 가지 옵션이 있습니다.


먼저 요소 배열을 ReactDOM.render에 전달하고 원하는 수의 React 요소를 해당 배열에 삽입 할 수 있습니다.


Option #1 

ReactDOM.render([<Button />, <Display />], mountNode);


일반적으로 렌더링 중인 모든 요소가 동적 소스에서 나오는 경우에 좋은 솔루션입니다. 그러나 여기서 수행하는 경우에는 적합하지 않습니다.


다른 옵션은 형제 React 요소를 다른 React 요소의 하위 요소로 만드는 것입니다. 예를 들어 div 요소로 묶을 수 있습니다.


옵션 # 2 

ReactDOM.render(
  <div>
    <Button />
    <Display />
  </div>,
  mountNode
);


React API는 이 중첩을 지원합니다. 사실, 새로운 DOM 부모 노드를 도입하지 않고 이와 같은 여러 인접 요소를 묶어야 하는 경우 React에는 특별한 객체가 있습니다. React.Fragment를 사용할 수 있습니다.


옵션 # 3 

ReactDOM.render(
  <React.Fragment>
    <Button />
    <Display />
  </React.Fragment>,
  mountNode
);

이 사례는 React에서 매우 일반적이므로 JSX 확장에는 단축키가 있습니다. React.Fragment를 입력하는 대신 빈 태그 <> </>를 사용할 수 있습니다.


옵션 #3+

ReactDOM.render(
  <>
    <Button />
    <Display />
  </>,
  mountNode
);


빈 태그는 React.Fragment 구문으로 변환됩니다. 이 구문을 사용하여 예제를 계속하겠습니다.


그러나 ReactDOM.render에 대한 첫 번째 인수를 방금 수행 한 중첩 트리 대신 단일 컴포넌트 호출로 만들어야 합니다. 이것은 본질적으로 코드 품질 환경 설정입니다. 구성 요소 계층 구조, 이름 및 관계에 대해 생각하게 합니다. 다음에 해봅시다.


최상위 컴포넌트 


Button 및 Display 구성 요소를 모두 호스팅 하는 최상위 구성 요소를 소개하겠습니다. 이제 문제는 이 새로운 부모 컴포넌트의 이름을 어떻게 정해야 하는가 입니다.


믿거나 말거나, 컴포넌트와 상태 / 프로스 요소의 이름을 짓는 것은 컴포넌트가 작동하고 수행하는 방식에 영향을 미치는 매우 어려운 작업입니다. 올바른 이름을 사용하면 올바른 디자인 결정을 내릴 수 있습니다. 시간을 내어 React 앱에 도입 한 모든 새로운 이름을 생각하십시오. 


이 새로운 상위 컴포넌트는 표시된 카운트를 증가 시키는 버튼이 있는 디스플레이를 호스팅 하므로 카운트 값 관리자라고 생각할 수 있습니다. 이름을 CountManager로 지정하겠습니다.

const CountManager = () => {
  return (
    <>
      <Button />
      <Display />
    </>
  );
};

ReactDOM.render(<CountManager />, mountNode);


새로운 디스플레이 구성 요소에 카운트 값을 표시하므로 더 이상 카운트 값을 버튼의 레이블로 표시 할 필요가 없습니다. 대신 레이블을 "+1"과 같은 것으로 변경할 수 있습니다.

const Button = () => {
  return (
    <button onClick={() => console.log('TODO: Increment counter')}>
      +1
    </button>
  );
};


더 이상 가질 수 없기 때문에 Button 구성 요소에서 state 요소도 제거했습니다. 새로운 요구 사항으로 인해 Button 및 Display 구성 요소 모두 카운트 상태 요소에 액세스 해야 합니다. 디스플레이 구성 요소가 표시하고 Button 구성 요소가 이를 업데이트합니다. 구성 요소가 형제 구성 요소가 소유 한 상태 요소에 액세스 해야 하는 경우, 한 가지 해결책은 해당 상태 요소를 한 레벨 위로 "상승"하여 상위 구성 요소 내에 정의하는 것입니다. 이 경우 부모는 방금 소개 한 CountManager 구성 요소입니다.


상태를 CountManager로 옮기면 컴포넌트 소품을 사용하여 부모에서 자식으로 데이터를 "흐르게"할 수 있습니다. 이것이 디스플레이 구성 요소에 카운트 값을 표시하기 위해 해야 ​​할 일입니다.

const Display = ({ content }) => (
  <pre>{content}</pre>
);

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

  return (
    <>
      <Button />
      <Display content={count} />
    </>
  );
};

ReactDOM.render(<CountManager />, mountNode);


CountManager에서 Button 구성 요소와 동일한 useState 줄을 어떻게 사용했는지 참고하십시오. 우리는 동일한 상태 요소를 해제하고 있습니다. 또한 소품을 통해 카운트 값을 디스플레이 구성 요소로 흘렀을 때 다른 이름 (콘텐츠)을 사용했습니다. 그건 정상입니다 똑같은 이름을 사용할 필요는 없습니다. 실제로 경우에 따라 새로운 일반 이름을 도입하면 하위 컴포넌트가 재사용 성이 높아 지므로 하위 컴포넌트에 더 좋습니다. 카운트 이외의 다른 숫자 값을 표시하기 위해 디스플레이 구성 요소를 재사용 할 수 있습니다.


부모 구성 요소는 자녀에게 동작을 전달할 수 있으므로 다음에 수행해야 합니다.