(SEB_FE) Section2 Unit6 React State & Props

PYM·2023년 3월 24일
0

(SEB_FE) SECTION2

목록 보기
9/19
post-thumbnail

state, props의 개념에 대해서 이해하고, 실제 프로젝트에 바르게 적용할 수 있다.
React 함수 컴포넌트(React Function Component)에서 state hook을 이용하여 state를 정의 및 변경할 수 있다.
React 컴포넌트(React Component)에 props를 전달할 수 있다.
이벤트 핸들러 함수를 만들고 React에서 이용할 수 있다.
실제 웹 애플리케이션의 컴포넌트를 보고 어떤 데이터가 state이고 props에 적합한지 판단할 수 있다.
실제 웹 애플리케이션 개발 시 적합한 state와 props의 위치를 스스로 정할 수 있다.
React의 단방향 데이터 흐름(One-way data flow)에 대해 자신의 언어로 설명할 수 있다.
JSX 문법의 기본과 컴포넌트 기반 개발에 대해서 숙지한다.
React Router DOM으로 React에서 SPA(Single-Page Application)을 구현할 수 있다.
state hook을 이용하여, 컴포넌트에서 데이터를 변화시킬 수 있다.
props를 이용하여, 부모 컴포넌트의 데이터를 자식 컴포넌트로 전달할 수 있다.
바람직한 컴포넌트 구조와 state와 props의 위치에 대해 고민한다.

🏀Props

  • 컴포넌트의 속성(property)을 의미.
    props는 성별이나 이름처럼 변하지 않는(immutable) 외부로부터 전달받은 값으로, 웹 애플리케이션에서 해당 컴포넌트가 가진 속성에 해당

  • 부모 컴포넌트(상위 컴포넌트)로부터 전달받은 값!

  • 객체 형태이다.
    props로 어떤 타입의 값도 넣어 전달할 수 있도록 props는 객체의 형태를 가진다.

  • 읽기 전용이다.
    외부로부터 전달받아서 변하지 않는 값이기 때문에 함부로 변경될 수 없다.

  • 클래스 컴포넌트뿐만 아니라 함수형 컴포넌트에서도 사용할 수 있다.

  • Props는 여러 개 지정할수 있다.

🏀How to use props

Props 사용하는 3단계!

  1. 하위 컴포넌트에 전달하고자 하는 값(data)과 속성을 정의한다.
  2. props를 이용하여 정의된 값과 속성을 전달한다.
  3. 전달받은 props를 렌더링한다.

예시와 함께 좀 더 자세하게 살펴보자.

우선 <Parent><Child> 라는 컴포넌트를 선언하고, <Parent> 컴포넌트 안에 <Child> 컴포넌트를 작성한다. 아래 코드와 같이!!

// 부모 컴포넌트에
function Parent() {
  return (
    <div className="parent">
      <h1>I'm the parent</h1>
    	// 아래에 만든 자식 컴포넌트를 넣어준다. 
      <Child />
    </div>
  );
};

function Child() {
  return (
    <div className="child"></div>
  );
};

이제 전달하고자 하는 속성을 정의해보자.
아래 코드처럼 전달하고자하는 속성을 중괄호 {}로 감싸서 적어주면 끝!

// 기본 형태 
<Child attribute={value} />

// text라는 속성을 선언하고 문자열 값을 할당해서 Child 컴포넌트에 전달하는 코드! 
<Child text={"I'm the eldest child"} />
 
// Parent 컴포넌트로 부터 전달받은 문자열 값을 React 컴포넌트(현재 Child)에 props로 전달하면, 
// 문자열= props가 되고 이 props가 필요한 모든 데이터를 가지고 와서 사용(렌더링)할 수 있게 된다! 
function Child(props) {
  return (
    <div className="child">
    		// 가져온 props의 text를 사용 중..! <p>안에 값으로 넣어준 것. 
    		// 즉 아래 코드는 <p>"I'm the eldest child"</p>와 같다 
    	  <p>{props.text}</p>
    </div>
  );
};

🏅 props.children

props를 전달하는 또 다른 방법으로 여는 태그와 닫는 태그의 사이에 value를 넣어 전달하는 방법이 있다.
이 경우 props.children을 이용하면 해당 value에 접근하여 사용할 수 있다.

function Parent() {
  return (
    <div className="parent">
        <h1>I'm the parent</h1>
    	// 이렇게 여는 태그, 닫는 태그 사이에 값을 넣고
        <Child>I'm the eldest child</Child>
    </div>
  );
};

function Child(props) {
  return (
    <div className="child">
    	// 요로코롬! 사용할 수 있다. 
        <p>{props.children}</p>
    </div>
  );
};

🏀State, 애플리케이션의 "상태"

변수가 살면서 변할 수 있는 값(mutable). 컴포너트 사용 중 컴포넌트 내부에서 변할 수 있는 값

인간이 살면서 아주 다양한 상태를 겪듯이, 컴퓨터도 상태라는 것이 있다.
예를 들면 쇼핑몰에서 쇼핑을 하면서 장바구니의 목록을 삭제하려고 체크박스를 선택한 상태와, 선택하지 않은 상태. 이 두가지 상태는 truefalse로도 구분해볼 수 있겠다.

체크 여부에 따라 구매할 물건의 개수나 구매 금액이 변경되고, 이에 따라 사용자의 화면 또한 달라질 것이다.

이처럼 컴포넌트 내에서 변할 수 있는 값, 즉 상태는 React state로 다뤄야 한다!

🏀State hook, useState

🏅 useState 사용법

React에서 제공하는 state 를 다루는 방법 중 하나!

  1. 우선 사용하기 위해서 import로 불러와야 한다.
    import { useState } from "react";

  2. 이후 useState 를 컴포넌트 안에서 호출한다.
    useState 를 호출한다는 것 = "state" 라는 변수를 선언하는 것 으로, 일반적인 변수는 함수가 끝날 때 사라지지만, state 변수는 React에 의해 함수가 끝나도 사라지지 않는다.

function CheckboxExample() {
  // useState 문법
  // const [state 저장 변수, state 갱신 함수] = useState(state 초깃값);

  // [isChecked, setIsChecked]는 useState 호출시 반환받는 배열로, 
  // 0번째 요소는 현재 상태 변수, 1번째 요소는 이 변수를 갱신할 수 있는 함수!
  // useState()안에 인자로 넘겨주는 값응 초깃값이다. 
  const [isChecked, setIsChecked] = useState(false); // 1번

  //...

  // useState 구조 분해 할당 예시
  const stateHookArray = useState(false); // 2번
  const isChecked = stateHookArray[0];
  const setIsChecked = stateHookArray[1];
}
  1. 이 state 변수에 저장된 값을 사용하려면 JSX 엘리먼트 안에 직접 불러서 사용하면 된다.
<span>{isChecked ? "Checked!!" : "Unchecked"}</span>

🏅 state 갱신하기

  1. state를 갱신하려면 state 변수를 갱신할 수 있는 함수인 setIsChecked(위 예시에서) 를 호출한다.

시스템의 흐름과 함께 살펴보자. 언제 state 갱신 함수를 호출할까?

사용자가 체크박스 값을 변경하면 onChange 이벤트가 이벤트 핸들러 함수인 handleChecked 를 호출하고, 이 함수가 setIsChecked 를 호출하게 된다.
아래 예시 코드를 보면서 다시 생각해보자.

function CheckboxExample() {
  const [isChecked, setIsChecked] = useState(false);

  // handleChecked 함수
  // 이 함수는 체크박스에 onChange이벤트가 발생하면 호출된다. 
  const handleChecked = (event) => {
    // 체크박스가 check되면 isChecked의 상태를 true로 바꿔줌. 
    setIsChecked(event.target.checked);
  };

  return (
    <div className="App">
      <input type="checkbox" checked={isChecked} onChange={handleChecked} />
      <span>{isChecked ? "Checked!!" : "Unchecked"}</span>
    </div>
  );
}

🏅 state hook 사용시의 주의점

  • React 컴포넌트는 state가 변경되면 새롭게 호출되고, 리렌더링된다.

  • React state는 꼭! 상태 변경 함수 호출로 변경해야 한다. 강제로 변경을 시도하면 리렌더링이 안 되거나 state가 제대로 변경되지 않기 때문에 하면 안 된다!


🏀React 데이터 흐름

React의 개발 방식의 가장 큰 특징은 페이지 단위가 아닌, 컴포넌트 단위로 시작한다는 점

즉, 페이지를 만들기 이전에 페이지를 구성하는 각각의 컴포넌트가 뭐가 있는지 확인하고(컴포넌트 계층 구조로 나누고), 그 컴포넌트를 먼저 만들고 이후에 컴포넌트들을 조립하는, 상향식(bottom-up)으로 앱을 만드는 것. 이것의 가장 큰 장점은 테스트가 쉽고 확장성이 좋다!

컴포넌트를 구분할 때는 단일 책임 원칙에 따른 구분을 하자. 하나의 컴포넌트는 한 가지 일만 한다는 것을 기억하기!

컴포넌트는 컴포넌트 바깥에서 props를 이용해 데이터를 마치 인자(arguments) 혹은 속성(attributes)처럼 전달받을 수 있다.
즉, 데이터를 전달하는 주체는 부모 컴포넌트가 된다. 이는 데이터 흐름이 하향식(top-down) 임을 의미한다.
단방향 데이터 흐름(one-way data flow)이라는 키워드가 React를 대표하는 설명 중 하나일 정도로 하향식 데이터 흐름 원칙은 매우매우 중요하다!!

또한 컴포넌트는 props를 통해 전달받은 데이터가 어디서 왔는지 전혀 알지 못한다.

모든 데이터를 "상태"로 둘 필요는 없다. 상태는 많아질수록 애플리케이션은 복잡해지기 때문에, 상태는 최소화하는 것이 가장 좋다.

어떤 데이터를 상태로 둬야 할까? 잘 모르겠을때 3가지 질문

  • 부모로부터 props를 통해 전달되는가? 그러면 확실히 state가 아니다.
  • 시간이 지나도 변하지 않는가? 그러면 확실히 state가 아니다
  • 컴포넌트 안의 다른 state나 props를 가지고 계산 가능한가? 그렇다면 state가 아니다

상태가 특정 컴포넌트에서만 유의미하다면, 특정 컴포넌트에만 두면 되니까 크게 어렵지 않지만, 만일 하나의 상태를 기반으로 두 컴포넌트가 영향을 받는다면 이때에는 공통 소유 컴포넌트를 찾아 그곳에 상태를 위치시켜야 한다.

profile
목표는 "함께 일하고 싶은, 함께 일해서 좋은" Front-end 개발자

0개의 댓글