SPACE RUMI

Hi, I am rumi. Let's Splattack!

[STUDY] 스터디/React Docs

React docs beta 한글 번역 : state: A Component's Memory - 상태: 컴포넌트의 메모리

백루미 2023. 2. 23. 22:37
반응형

상태: 컴포넌트의 메모리

컴포넌트는 상호 작용의 결과로 화면의 내용을 변경해야 하는 경우가 많습니다. 양식에 입력하면 입력 필드가 업데이트되어야 하고, 이미지 캐러셀에서 '다음'을 클릭하면 표시되는 이미지가 변경되어야 하며, '구매'를 클릭하면 제품이 장바구니에 담겨야 합니다. 컴포넌트는 현재 입력값, 현재 이미지, 장바구니와 같은 것들을 "기억"해야 합니다. React에서는 이런 종류의 컴포넌트별 메모리를 state라고 부릅니다.

 

학습 내용

  • useState Hook으로 상태 변수를 추가하는 방법
  • useState Hook이 반환하는 값 쌍
  • 상태 변수를 두 개 이상 추가하는 방법
  • state를 로컬이라고 부르는 이유

 

일반 변수로 충분하지 않을 때 

다음은 조각상 이미지를 렌더링하는 컴포넌트입니다. "Next" 버튼을 클릭하면 인덱스를 1, 2로 변경하여 다음 조각상 이미지를 표시해야 합니다. 하지만 이 방법은 작동하지 않습니다(시도해 보세요!):

import { sculptureList } from './data.js';

export default function Gallery() {
  let index = 0;

  function handleClick() {
    index = index + 1;
  }

  let sculpture = sculptureList[index];
  return (
    <>
      <button onClick={handleClick}>
        Next
      </button>
      <h2>
        <i>{sculpture.name} </i> 
        by {sculpture.artist}
      </h2>
      <h3>  
        ({index + 1} of {sculptureList.length})
      </h3>
      <img 
        src={sculpture.url} 
        alt={sculpture.alt}
      />
      <p>
        {sculpture.description}
      </p>
    </>
  );
}

 

handleClick 이벤트 핸들러가 로컬 변수 인덱스를 업데이트하고 있습니다. 하지만 두 가지 이유로 인해 변경 사항이 표시되지 않습니다:

  • 로컬 변수는 렌더링 사이에 지속되지 않습니다.
    React는 이 컴포넌트를 두 번째로 렌더링할 때 로컬 변수에 대한 변경 사항을 고려하지 않고 처음부터 렌더링합니다.
  • 로컬 변수를 변경해도 렌더링이 트리거되지 않습니다.
    React는 새로운 데이터로 컴포넌트를 다시 렌더링해야 한다는 사실을 인지하지 못합니다.

 

컴포넌트를 새 데이터로 업데이트하려면 두 가지 작업이 필요합니다:

1. 렌더링 사이에 데이터를 유지합니다.
2. React를 트리거하여 새로운 데이터로 컴포넌트를 렌더링합니다(재렌더링).

 

useState Hook은 이 두 가지를 제공합니다:

1. 렌더링 사이에 데이터를 유지하는 state 변수.
2. 변수를 업데이트하고 React가 컴포넌트를 다시 렌더링하도록 트리거하는 state setter 함수.

 

상태 변수 추가하기 

상태 변수를 추가하려면 파일 상단에 있는 React에서 useState를 가져옵니다:

import { useState } from 'react';

그리고 이 코드를

let index = 0;

이 코드로 바꿉니다.

const [index, setIndex] = useState(0);

index는 state 변수이고 setIndex는 setter 함수입니다.

여기서 [  ] 구문은 배열 분해라고 하며 배열에서 값을 읽을 수 있게 해줍니다.
useState가 반환하는 배열에는 항상 정확히 두 개의 항목이 있습니다.

이것이 handleClick에서 함께 작동하는 방식입니다:

function handleClick() {
  setIndex(index + 1);
}

 

이제 "Next" 버튼을 클릭하면 현재 조각상 이미지가 전환됩니다:

import { useState } from 'react';
import { sculptureList } from './data.js';

export default function Gallery() {
  const [index, setIndex] = useState(0);

  function handleClick() {
    setIndex(index + 1);
  }

  let sculpture = sculptureList[index];
  return (
    <>
      <button onClick={handleClick}>
        Next
      </button>
      <h2>
        <i>{sculpture.name} </i> 
        by {sculpture.artist}
      </h2>
      <h3>  
        ({index + 1} of {sculptureList.length})
      </h3>
      <img 
        src={sculpture.url} 
        alt={sculpture.alt}
      />
      <p>
        {sculpture.description}
      </p>
    </>
  );
}

 

첫 번째 Hook 만나기

React에서는 useState를 비롯해 "use"로 시작하는 다른 모든 함수를 Hook이라고 부릅니다.

Hook은 React가 렌더링하는 동안에만 사용할 수 있는 특별한 함수입니다(다음 페이지에서 더 자세히 설명하겠습니다). 
이를 통해 다양한 React 기능을 "연결"할 수 있습니다.

State는 그 기능 중 하나에 불과하지만 다른 Hook은 나중에 만나게 될 것입니다.

 

함정

Hook("use"로 시작하는 함수)은 컴포넌트의 최상위 레벨 또는 자체 Hook에서만 호출할 수 있습니다. 조건, 루프 또는 기타 중첩된 함수 내부에서는 Hook을 호출할 수 없습니다. Hook은 함수이지만 컴포넌트의 필요에 대한 무조건적인 선언으로 생각하면 도움이 됩니다. 파일 상단에서 모듈을 "import"하는 방식과 유사하게 컴포넌트 상단에서 React 기능을 "use"합니다.

 

useState의 해부학 

useState를 호출하는 것은 이 컴포넌트가 무언가를 기억하기를 원한다는 것을 React에 알리는 것입니다:

const [index, setIndex] = useState(0);

이 경우 React가 index를 기억하기를 원합니다.

이 쌍의 이름은 const [something, setSomething]과 같이 지정하는 것이 일반적입니다. 
원하는 대로 이름을 지정할 수 있지만, 규칙을 따르면 프로젝트 전반에서 이해하기 쉽습니다.

useState의 유일한 인수는 state 변수의 초기 값입니다. 이 예시에서는 useState(0)을 사용하여 인덱스의 초기값을 0으로 설정했습니다.

컴포넌트가 렌더링될 때마다 useState는 두 개의 값을 포함하는 배열을 제공합니다:

저장한 값을 가진 상태 변수(index).
상태 변수를 업데이트하고 React가 컴포넌트를 다시 렌더링하도록 트리거할 수 있는 상태 세터 함수(setIndex)가 있습니다.

실제 작동 방식은 다음과 같습니다:

const [index, setIndex] = useState(0);
  1. 컴포넌트가 처음으로 렌더링됩니다. 인덱스의 초기값으로 0을 useState에 전달했기 때문에 [0, setIndex]를 반환합니다. React는 0이 최신 상태 값임을 기억합니다.
  2. 상태를 업데이트합니다. 사용자가 버튼을 클릭하면 setIndex(index + 1)를 호출합니다. index가 0이므로 setIndex(1)이 됩니다. 이렇게 하면 React가 index가 이제 1이라는 것을 기억하고 다른 렌더링을 트리거합니다.
  3. 컴포넌트의 두 번째 렌더링입니다. React는 여전히 useState(0)을 보지만, 사용자가 index를 1로 설정한 것을 기억하기 때문에 대신 [1, setIndex]를 반환합니다.
  4. 그리고 계속됩니다!

 

컴포넌트에 여러 상태 변수 부여하기 

하나의 컴포넌트에 원하는 만큼 많은 유형의 상태 변수를 가질 수 있습니다. 이 컴포넌트에는 숫자 index와, 'Show details'를 클릭하면 토글되는 boolean 타입의 showMore라는 두 개의 상태 변수가 있습니다:

import { useState } from 'react';
import { sculptureList } from './data.js';

export default function Gallery() {
  const [index, setIndex] = useState(0);
  const [showMore, setShowMore] = useState(false);

  function handleNextClick() {
    setIndex(index + 1);
  }

  function handleMoreClick() {
    setShowMore(!showMore);
  }

  let sculpture = sculptureList[index];
  return (
    <>
      <button onClick={handleNextClick}>
        Next
      </button>
      <h2>
        <i>{sculpture.name} </i> 
        by {sculpture.artist}
      </h2>
      <h3>  
        ({index + 1} of {sculptureList.length})
      </h3>
      <button onClick={handleMoreClick}>
        {showMore ? 'Hide' : 'Show'} details
      </button>
      {showMore && <p>{sculpture.description}</p>}
      <img 
        src={sculpture.url} 
        alt={sculpture.alt}
      />
    </>
  );
}

이 예제에서 index와 showMore처럼 서로 관련이 없는 상태 변수는 여러 개를 사용하는 것이 좋습니다. 하지만 두 개의 상태 변수를 자주 함께 변경하는 경우에는 하나의 변수로 결합하는 것이 더 좋을 수 있습니다. 예를 들어 필드가 많은 폼이 있는 경우 필드별로 상태 변수를 사용하는 것보다 객체를 보관하는 단일 상태 변수를 사용하는 것이 더 편리합니다. 상태 구조 선택에 더 많은 팁이 있습니다.

 

Deep Dive - React는 어떤 상태를 반환할지 어떻게 알 수 있을까요?

useState 호출이 어떤 상태 변수를 참조하는지에 대한 정보를 받지 못한다는 것을 눈치채셨을 것입니다. useState에 전달되는 '식별자'가 없는데, 어떤 상태 변수를 반환할지 어떻게 알 수 있을까요? 함수를 파싱하는 것과 같은 마법에 의존할까요? 대답은 '아니오'입니다.

대신 Hook은 간결한 구문을 구현하기 위해 동일한 컴포넌트의 모든 렌더링에서 안정적인 호출 순서에 의존합니다. 위의 규칙("최상위 수준에서만 Hook 호출")을 따르면 Hook은 항상 같은 순서로 호출되기 때문에 실제로 잘 작동합니다. 또한 린터 플러그인(linter plugin)은 대부분의 실수를 잡아냅니다.

내부적으로 React는 모든 컴포넌트에 대해 state 쌍의 배열을 보유합니다. 또한 렌더링 전에 0으로 설정된 현재 쌍 index를 유지합니다. useState를 호출할 때마다 React는 다음 state 쌍을 제공하고 인덱스를 증가시킵니다. 이 메커니즘에 대한 자세한 내용은 React Hook에서 확인할 수 있습니다: 마법이 아니라 배열일 뿐입니다.

이 예시에서는 React를 사용하지 않지만, useState가 내부적으로 어떻게 작동하는지에 대한 아이디어를 제공합니다:

let componentHooks = [];
let currentHookIndex = 0;

// React 내에서 useState가 작동하는 방식(단순화)
function useState(initialState) {
  let pair = componentHooks[currentHookIndex];
  if (pair) {
    // 이것은 첫 번째 렌더링이 아닙니다,
    // 상태 쌍이 이미 존재합니다.
    // 반환하고 다음 Hook 호출을 준비합니다.
    currentHookIndex++;
    return pair;
  }

  // 렌더링하는 것은 이번이 처음입니다,
  // 상태 쌍을 생성하고 저장합니다.
  pair = [initialState, setState];

  function setState(nextState) {
    // 사용자가 상태 변경을 요청할 때,
    // 새 값을 쌍에 넣습니다.
    pair[0] = nextState;
    updateDOM();
  }

  // 향후 렌더링을 위해 쌍을 저장하고
  // 다음 Hook 호출을 준비합니다.
  componentHooks[currentHookIndex] = pair;
  currentHookIndex++;
  return pair;
}

function Gallery() {
  // 각 useState() 호출은 다음 쌍을 가져옵니다.
  const [index, setIndex] = useState(0);
  const [showMore, setShowMore] = useState(false);

  function handleNextClick() {
    setIndex(index + 1);
  }

  function handleMoreClick() {
    setShowMore(!showMore);
  }

  let sculpture = sculptureList[index];
  // 이 예제에서는 React를 사용하지 않으므로
  // JSX 대신 출력 객체를 반환합니다.
  return {
    onNextClick: handleNextClick,
    onMoreClick: handleMoreClick,
    header: `${sculpture.name} by ${sculpture.artist}`,
    counter: `${index + 1} of ${sculptureList.length}`,
    more: `${showMore ? 'Hide' : 'Show'} details`,
    description: showMore ? sculpture.description : null,
    imageSrc: sculpture.url,
    imageAlt: sculpture.alt
  };
}

function updateDOM() {
  // 현재 Hook 인덱스를
  // 컴포넌트를 렌더링하기 전에 재설정합니다.
  currentHookIndex = 0;
  let output = Gallery();

  // 출력과 일치하도록 DOM을 업데이트합니다.
  // 이 부분은 React가 대신 해줍니다.
  nextButton.onclick = output.onNextClick;
  header.textContent = output.header;
  moreButton.onclick = output.onMoreClick;
  moreButton.textContent = output.more;
  image.src = output.imageSrc;
  image.alt = output.imageAlt;
  if (output.description !== null) {
    description.textContent = output.description;
    description.style.display = '';
  } else {
    description.style.display = 'none';
  }
}

let nextButton = document.getElementById('nextButton');
let header = document.getElementById('header');
let moreButton = document.getElementById('moreButton');
let description = document.getElementById('description');
let image = document.getElementById('image');
let sculptureList = [{
  name: 'Homenaje a la Neurocirugía',
  artist: 'Marta Colvin Andrade',
  description: 'Although Colvin is predominantly known for abstract themes that allude to pre-Hispanic symbols, this gigantic sculpture, an homage to neurosurgery, is one of her most recognizable public art pieces.',
  url: 'https://i.imgur.com/Mx7dA2Y.jpg',
  alt: 'A bronze statue of two crossed hands delicately holding a human brain in their fingertips.'  
}, {
  name: 'Floralis Genérica',
  artist: 'Eduardo Catalano',
  description: 'This enormous (75 ft. or 23m) silver flower is located in Buenos Aires. It is designed to move, closing its petals in the evening or when strong winds blow and opening them in the morning.',
  url: 'https://i.imgur.com/ZF6s192m.jpg',
  alt: 'A gigantic metallic flower sculpture with reflective mirror-like petals and strong stamens.'
}, {
  name: 'Eternal Presence',
  artist: 'John Woodrow Wilson',
  description: 'Wilson was known for his preoccupation with equality, social justice, as well as the essential and spiritual qualities of humankind. This massive (7ft. or 2,13m) bronze represents what he described as "a symbolic Black presence infused with a sense of universal humanity."',
  url: 'https://i.imgur.com/aTtVpES.jpg',
  alt: 'The sculpture depicting a human head seems ever-present and solemn. It radiates calm and serenity.'
}, {
  name: 'Moai',
  artist: 'Unknown Artist',
  description: 'Located on the Easter Island, there are 1,000 moai, or extant monumental statues, created by the early Rapa Nui people, which some believe represented deified ancestors.',
  url: 'https://i.imgur.com/RCwLEoQm.jpg',
  alt: 'Three monumental stone busts with the heads that are disproportionately large with somber faces.'
}, {
  name: 'Blue Nana',
  artist: 'Niki de Saint Phalle',
  description: 'The Nanas are triumphant creatures, symbols of femininity and maternity. Initially, Saint Phalle used fabric and found objects for the Nanas, and later on introduced polyester to achieve a more vibrant effect.',
  url: 'https://i.imgur.com/Sd1AgUOm.jpg',
  alt: 'A large mosaic sculpture of a whimsical dancing female figure in a colorful costume emanating joy.'
}, {
  name: 'Ultimate Form',
  artist: 'Barbara Hepworth',
  description: 'This abstract bronze sculpture is a part of The Family of Man series located at Yorkshire Sculpture Park. Hepworth chose not to create literal representations of the world but developed abstract forms inspired by people and landscapes.',
  url: 'https://i.imgur.com/2heNQDcm.jpg',
  alt: 'A tall sculpture made of three elements stacked on each other reminding of a human figure.'
}, {
  name: 'Cavaliere',
  artist: 'Lamidi Olonade Fakeye',
  description: "Descended from four generations of woodcarvers, Fakeye's work blended traditional and contemporary Yoruba themes.",
  url: 'https://i.imgur.com/wIdGuZwm.png',
  alt: 'An intricate wood sculpture of a warrior with a focused face on a horse adorned with patterns.'
}, {
  name: 'Big Bellies',
  artist: 'Alina Szapocznikow',
  description: "Szapocznikow is known for her sculptures of the fragmented body as a metaphor for the fragility and impermanence of youth and beauty. This sculpture depicts two very realistic large bellies stacked on top of each other, each around five feet (1,5m) tall.",
  url: 'https://i.imgur.com/AlHTAdDm.jpg',
  alt: 'The sculpture reminds a cascade of folds, quite different from bellies in classical sculptures.'
}, {
  name: 'Terracotta Army',
  artist: 'Unknown Artist',
  description: 'The Terracotta Army is a collection of terracotta sculptures depicting the armies of Qin Shi Huang, the first Emperor of China. The army consisted of more than 8,000 soldiers, 130 chariots with 520 horses, and 150 cavalry horses.',
  url: 'https://i.imgur.com/HMFmH6m.jpg',
  alt: '12 terracotta sculptures of solemn warriors, each with a unique facial expression and armor.'
}, {
  name: 'Lunar Landscape',
  artist: 'Louise Nevelson',
  description: 'Nevelson was known for scavenging objects from New York City debris, which she would later assemble into monumental constructions. In this one, she used disparate parts like a bedpost, juggling pin, and seat fragment, nailing and gluing them into boxes that reflect the influence of Cubism’s geometric abstraction of space and form.',
  url: 'https://i.imgur.com/rN7hY6om.jpg',
  alt: 'A black matte sculpture where the individual elements are initially indistinguishable.'
}, {
  name: 'Aureole',
  artist: 'Ranjani Shettar',
  description: 'Shettar merges the traditional and the modern, the natural and the industrial. Her art focuses on the relationship between man and nature. Her work was described as compelling both abstractly and figuratively, gravity defying, and a "fine synthesis of unlikely materials."',
  url: 'https://i.imgur.com/okTpbHhm.jpg',
  alt: 'A pale wire-like sculpture mounted on concrete wall and descending on the floor. It appears light.'
}, {
  name: 'Hippos',
  artist: 'Taipei Zoo',
  description: 'The Taipei Zoo commissioned a Hippo Square featuring submerged hippos at play.',
  url: 'https://i.imgur.com/6o5Vuyu.jpg',
  alt: 'A group of bronze hippo sculptures emerging from the sett sidewalk as if they were swimming.'
}];

// UI를 초기 상태와 일치하게 만듭니다.
updateDOM();

React를 사용하기 위해 이 모델을 이해할 필요는 없지만, 유용한 멘탈 모델이 될 수 있습니다.

 

state는 독립적이고 비공개입니다. 

상태는 화면의 컴포넌트 인스턴스에 로컬입니다. 즉, 동일한 컴포넌트를 두 번 렌더링하면 각 사본은 완전히 격리된 상태를 갖게 됩니다! 그 중 하나를 변경해도 다른 컴포넌트에는 영향을 미치지 않습니다.

이 예시에서는 앞의 갤러리 컴포넌트가 로직을 변경하지 않고 두 번 렌더링되었습니다. 각 갤러리 내부의 버튼을 클릭해 보세요. 각각의 상태가 독립적인 것을 확인할 수 있습니다:

import Gallery from './Gallery.js';

export default function Page() {
  return (
    <div className="Page">
      <Gallery />
      <Gallery />
    </div>
  );
}
import { useState } from 'react';
import { sculptureList } from './data.js';

export default function Gallery() {
  const [index, setIndex] = useState(0);
  const [showMore, setShowMore] = useState(false);

  function handleNextClick() {
    setIndex(index + 1);
  }

  function handleMoreClick() {
    setShowMore(!showMore);
  }

  let sculpture = sculptureList[index];
  return (
    <section>
      <button onClick={handleNextClick}>
        Next
      </button>
      <h2>
        <i>{sculpture.name} </i> 
        by {sculpture.artist}
      </h2>
      <h3>  
        ({index + 1} of {sculptureList.length})
      </h3>
      <button onClick={handleMoreClick}>
        {showMore ? 'Hide' : 'Show'} details
      </button>
      {showMore && <p>{sculpture.description}</p>}
      <img 
        src={sculpture.url} 
        alt={sculpture.alt}
      />
    </section>
  );
}

이것이 바로 모듈 상단에 선언하는 일반 변수와 상태의 차이점입니다. 상태는 특정 함수 호출이나 코드의 특정 위치에 연결되지 않지만 화면의 특정 위치에 "로컬"입니다. 두 개의 <Gallery /> 컴포넌트를 렌더링했으므로 해당 상태는 별도로 저장됩니다.

또한 Page 컴포넌트는 Gallery 상태나 Gallery의 존재 여부에 대해 아무것도 "알지 못한다"는 점에 주목하세요. props와 달리 state는 이를 선언하는 컴포넌트에게 완전히 비공개입니다. 부모 컴포넌트는 이를 변경할 수 없습니다. 따라서 나머지 컴포넌트에 영향을 주지 않고 컴포넌트에 상태를 추가하거나 제거할 수 있습니다.

두 Gallery의 상태를 동기화하려면 어떻게 해야 할까요? React에서 이를 수행하는 올바른 방법은 자식 컴포넌트에서 state를 제거하고 가장 가까운 공유 부모 컴포넌트에 추가하는 것입니다. 다음 몇 페이지는 단일 컴포넌트의 state를 구성하는 데 초점을 맞추겠지만, 이 주제는 컴포넌트 간 상태 공유하기 에서 다시 다룰 것입니다.

 

요약

  • 컴포넌트가 렌더링 사이에 일부 정보를 "기억"해야 할 때 상태 변수를 사용합니다.
  • 상태 변수는 useState Hook을 호출하여 선언합니다.
  • Hook은 "use"로 시작하는 특수 함수입니다. state와 같은 React 기능을 "hook"할 수 있게 해줍니다.
  • Hook은 import를 떠올리게 할 수 있는데, 무조건 호출해야 합니다.
    useState를 포함한 Hook 호출은 컴포넌트나 다른 Hook의 최상위 레벨에서만 유효합니다.
  • useState Hook은 현재 상태와 이를 업데이트하는 함수라는 값 쌍을 반환합니다.
  • 상태 변수는 둘 이상 가질 수 있습니다. 내부적으로 React는 순서대로 일치시킵니다.
  • 상태는 컴포넌트간에 비공개입니다. 두 곳에서 렌더링하면 각 복사본은 고유한 상태를 갖게 됩니다.

 

과제 1 / 4: 갤러리 완성하기 
마지막 조각상 이미지에서 "다음"을 누르면 코드가 충돌합니다. 로직을 수정하여 충돌을 방지하세요. 이벤트 핸들러에 추가 로직을 추가하거나 동작이 불가능할 때 버튼을 비활성화하여 이 작업을 수행할 수 있습니다.

충돌을 수정한 후 이전 조각을 표시하는 "이전" 버튼을 추가합니다. 첫번째 조각상 이미지 에서는 충돌이 발생하지 않아야 합니다.

https://codesandbox.io/s/2juca-2caebteo-d4v8e4?file=/src/StateComponentsMemory/CompleteTheGallery.js

 

과제 2/4: 멈춘 양식 입력 문제 해결

입력 필드에 입력해도 아무 것도 표시되지 않습니다. 입력값이 빈 문자열로 '고착'된 것과 같습니다.
첫 번째 <input>의 값은 항상 첫 번째 이름 변수와 일치하도록 설정되고, 두 번째 <input>의 값은 항상 마지막 이름 변수와 일치하도록 설정됩니다. 맞습니다. 두 입력 모두 최신 사용자 입력(예: target.value)을 기반으로 변수를 업데이트하려고 시도하는 onChange 이벤트 핸들러가 있습니다. 그러나 변수는 재렌더링 사이에 해당 값을 "기억"하지 못하는 것 같습니다. 대신 상태 변수를 사용하여 이 문제를 해결하세요.

https://codesandbox.io/s/2juca-2caebteo-d4v8e4?file=/src/StateComponentsMemory/FixStuckFormInputs.js

 

과제 3/4: 충돌 수정 

다음은 사용자가 피드백을 남길 수 있는 작은 양식입니다. 피드백이 제출되면 감사 메시지가 표시되어야 합니다. 그러나 "Rendered fewer hooks than expected. (예상보다 적은 수의 hooks를 렌더링했습니다)"라는 오류 메시지와 함께 충돌이 발생합니다. 실수를 발견하고 수정할 수 있나요?

https://codesandbox.io/s/2juca-2caebteo-d4v8e4?file=/src/StateComponentsMemory/FixACrash.js

 

과제 4/4: 불필요한 상태 제거하기 
이 예제에서는 버튼을 클릭하면 사용자의 이름을 물어본 다음 사용자에게 인사하는 알림을 표시해야 합니다. 상태를 사용하여 이름을 유지하려고 했지만 어떤 이유로 항상 "Hello, !"가 표시됩니다.

이 코드를 수정하려면 불필요한 상태 변수를 제거하세요. (왜 이것이 작동하지 않는지에 대해서는 나중에 설명하겠습니다.)

이 상태 변수가 불필요한 이유를 설명해 주시겠어요?

https://codesandbox.io/s/2juca-2caebteo-d4v8e4?file=/src/StateComponentsMemory/RemoveUnnecessaryState.js

 

발표 요약)

const [state, setState] = useState<type>(초기값)

1. React Hook 중 하나인 useState는 [state, setState] 두 쌍의 배열을 가진다.
2. 배열의 첫번째(state)는 현재 상태를 가지고, setState는 현재 상태를 변경시킨다.
3. 상태를 변경시킬때는 무조건 setter함수인 setState를 사용한다.
4. 상태는 private하기 때문에, 여러곳에서 렌더링 하면 각각의 고유한 state를 갖게된다.
5. Hook 호출은 컴포넌트의 최상단에 위치해야하며 조건문에 넣을수없다.
반응형