S2 Unit 6. React State&Props

나현·2022년 9월 30일
0

학습일지

목록 보기
23/53
post-thumbnail

💡 이번에 배운 내용

  • Section2.
    서버와 통신이 가능한 구조적인 Web App을 만들 수 있다.
  • Unit6. React State&Props : React의 Props, State, 이벤트 처리, controlled Component 등에 대해 학습한다.

느낀점

이번에도 state와 props 실습과 과제를 해보면서 웹 앱을 만들어보니 무척 재미있었다. 아무래도 무언가를 만들어보고 눈으로 동작하는 것을 확인해보는 게 프론트엔드의 큰 재미이지 않을까? 쉽지많은 않은 개념이지만 이번에는 시간이 좀 있어서 내용을 읽어보고 여러 번 실습하다보니 저번보다는 좀 더 쉽게 이해할 수 있었다. 리액트 생명주기를 살짝 맛보니 어질어질하던데, 이렇게 계속 공부하다보면 리액트도 잘 해낼 수 있지않을까?


키워드

props, state, useState, Controlled Component, 단방향 데이터 흐름(one-way data flow)


학습내용

Ch1. Props

props는 외부로부터 전달받은 값으로 해당 컴포넌트의 속성(property)을 뜻한다.
이 props는 보통 상위 컴포넌트(부모 컴포넌트)에서 속성과 속성값으로 해당 컴포넌트에 전달된다. state와 달리 한 번 할당되면 변하지 않는 값이다.
상위 컴포넌트에서 해당 컴포넌트를 작성할 때 props값을 해당 컴포넌트의 전달인자로 전달한다. 이렇게 상위에서 하위로 전달인자를 받기 때문에 이를 하향식(top-down), 단방향 데이터 흐름(one-way data flow)이라고 한다.
해당 컴포넌트에서는 상위 컴포넌트에서 전달해준 전달인자를 값으로 받아 요소를 리턴하는데 활용할 수 있고, 이 요소를 반환한다.
props는 상위 컴포넌트에서 받은 속성, 속성값을 객체의 형태로 받는다.
또한 하위 컴포넌트에서 props를 수정하면 상위 컴포넌트에 영향을 미치므로 변경될 수 없다.
따라서 이 props의 형식은 객체이며 읽을 수만 있다.

props 사용

props는 다음과 같은 순서로 사용한다.

1) 해당 컴포넌트가 되는 하위 컴포넌트를 정의할 때, 매개변수를 작성하고 전달받고자 하는 값, 속성을 정의한다.
이 때 매개변수는 객체형태이며 전달받는 값은 키:값의 형태로 각각 속성, 속성값이다.
2) 상위 컴포넌트에서 하위 컴포넌트에 속성="값"의 형태로 입력하여
하위 컴포넌트에 전달하고자 하는 값(data)과 속성을 입력한다.
3) 하위 컴포넌트에서 해당 속성, 값을 객체형태로 전달인자로 받아 렌더링한다.

아래 예제는 props를 사용하는 예제이다.

function Parent() {
  return (
    <div className="parent">
      <h1>Parent Component</h1>
      <Child1 text={"first child"} />
      <Child2>second child</Child>
    </div>
  );
};

function Child1(props) {
  return (
    <div className="child">
      <p>{props.text}</p>
    </div>
  );
};

function Child2(props) {
  return (
    <div className="child">
      {/* props.children는 해당 컴포넌트 안의 내용들을 전달인자로 받는다.*/}
      <p>{props.children}</p>
    </div>
  );
};

위 예제에서 props.children은 Child2 컴포넌트 안의 요소들을 담은 배열의 형태로 가져온다. 각 요소는 태그형태일 경우 객체이다.

Ch2. State

state는 컴포넌트를 사용하는 동안 내부에서 변하는 값으로 말 그대로 (지정한) 상태를 의미한다.
보통 이벤트나 함수에 의해 변경되어야 하거나 사용해야 하는 변수를 state로 선언한다.(ex. 체크 여부, input입력값 받기, 토글 이벤트 등)
state는 컴포넌트 안에서 선언하고 사용하지만 함수가 끝나도 선언한 state는 사용할 수 있다.

useState 사용

리액트에서는 state를 제어하기 위해 useState라는 함수를 제공한다.
사용방법은 아래와 같다.

1) useState를 사용하려면 먼저 import로 불러와야 한다.

import {useState} from 'React';

2) 사용할 컴포넌트 안에서 useState를 호출한다.
다음과 같이 배열 구조 분해로 초기 변수, 변수를 변경할 함수를 할당한다.

const [state할당변수, state변수변경함수]=useState(초기값);

상태를 변경할 때는 배열의 1번째인덱스의 변수 변경함수로만 가능하다.
함수로 변경된 상태는 변수에 할당되고,
변수의 초기값은 useState의 소괄호 안에 작성한다.
변수의 값을 변경할 때는 변경함수의 전달인자로 변경하고자 하는 값을 넣는다.
ex)

on, off상태를 나타내기 위해
on, off 상태를 변수 onOffState에 저장하고,
초기값은 off로 설정한다.
그리고 on, off 상태를 changeOnOff함수로 변경할 때 아래와 같이 사용한다.

const [onOffState, changeOnOff]=useState('off');
//on으로 상태를 변경할 때
changeOnOff('on');

3) state를 사용할 때는 설정한 state변수명을 이용한다. 값을 변경해야할 때는 반드시 설정한 state변경함수를 사용한다.
state변경함수를 사용하지 않고 강제로 변수를 할당하면 제대로 작동하지 않는다.

4) state가 변경되면 리액트가 갱신된 state값으로 해당 컴포넌트를 다시 렌더링한다.

Ch3. 이벤트 처리

리액트에서 이벤트를 다루는 방법은 기존 자바스크립트의 DOM을 다루는 것과 비슷하지만 차이가 있다.

  • 엘리먼트에 on이벤트 사용시 카멜케이스를 사용한다.
    리액트 DOM은 HTML보다 자바스크립트에 가깝기 때문이다.
  • 이벤트에 함수를 할당할 때 {}로 함수 자체를 전달한다.(함수실행문X)
    때문에 함수를 실행문이 필요하다면 화살표 함수를 사용해 내부에 함수를 실행해야 한다.

아래는 자주 사용하는 이벤트인 onClick, onChange 등을 활용한 예제다.

//기존 유저 데이터
const allUserData=[
  {
    id:1,
    name: 'Amy',
  },
  {
    id:2,
    name: 'Bob',
  },
];

//Form 컴포넌트
const UserForm = () => {
  //1. state 설정
  //이름 정의 state 설정. 초기값은 빈 문자열
  const [userName, setUserName] = useState("");
  //새로운 유저를 받아들이기 위한 state 설정. 초기값은 기존 유저 데이터
  const [userData, setUserData] = useState(allUserData);
  
  //2. 가입 버튼 클릭 이벤트: 클릭시 입력한 정보를 유저 데이터에 전달
  const joinBtnClick = () => {
    //작성한 유저정보를 객체 형태로 할당한다.
    const userDataObj={
      id:userData.length+1, //id는 데이터가 추가되는 순서
      name:userName,
    }
    //유저정보 객체를 기존 유저 데이터에 추가
    //기존 데이터의 맨 앞에 추가하기 위해 구조분해할당을 이용
    setUserData([userDataObj, ...userData]);
  };
  
  //3. 이름 input 입력 이벤트
  const changeName=(event)=>{
    setUserName(event.target.value);
  }
  
  //4. 반환
  return (
    <div className="userForm_wrapper">
      {/* 변경된 userName과 input의 value가 같아야 한다. */}
      <input type="text" 
        placeholder="이름을 입력하세요"
        className="userForm__nameInput" 
        onChange={changeName}
        value={userName}>
      </input>
      <button 
        className="userForm__joinBtn"
        onClick={joinBtnClick}>
        JOIN
      </button>
    </div>
  );
};

위 예제처럼 리액트가 state를 통제할 수 있는 컴포넌트를 Controlled Component라고 한다.

Ch4. React 데이터 흐름

이제까지 학습한 컴포넌트의 개념과 props, state 개념을 활용하여 리액트 웹앱을 만들 수 있다.
배운 내용을 활용해 웹 앱 설계에 대해 정리해보면 다음과 같다.

  • 리액트는 컴포넌트 단위로 작업하므로, 웹 앱 설계시 와이어프레임을 토대로 컴포넌트 단위로 나누어 설계한다.
  • 단일 책임: 하나의 컴포넌트는 한 가지 일만 한다.
  • 상향식(bottom-up) 컴포넌트 조립: 컴포넌트를 정했다면 가장 작은 컴포넌트부터 작업 후 조립하는 방식으로 작업한다. 테스트가 쉬우며 확장성이 좋다.
  • 하향식(top-down) 데이터 흐름: 자식 컴포넌트에서 사용할 데이터(props 등)는 부모 컴포넌트에서 전달한다. 그러면 부모에서 자식으로 데이터가 흐르는 것처럼 되는데 이를 단방향 데이터 흐름(one-way data flow)이라고 한다.
  • 두 개 이상의 컴포넌트가 공통의 state를 사용해야할 때는 그 컴포넌트의 공통된 부모 컴포넌트에 state를 선언한다. 그리고 필요한 state 값은 각 컴포넌트에 props로 전달하면 된다.
  • props와 state의 구분하기
    • 해당 컴포넌트에서 선언하지 않고 부모로부터 전달받는다면 props이다.
    • 반면 해당 컴포넌트에서 선언하여 상태가 변해야 한다면 state다.
    • 부모 컴포넌트에서 state로 선언한 값을 props로 자식 컴포넌트에 전달한다면 부모에서는 state지만 자식 입장에서는 state가 아니라 props이다.
    • 해당 컴포넌트 안에서 다른 state에 영향을 받는다면 state가 아니다.

질문해보기

1. Hook이란?
공식문서에 따르면 Hook은 함수 컴포넌트에서 리액트 state와 생명주기 기능(lifecycle features)을 “연동(hook into)“할 수 있게 해주는 함수이다. (생명주기에 대해서는 추후 학습 예정)
이번에 배운 useState 도 바로 Hook인다. 리액트는 useState 같은 내장 Hook을 여럿 제공하는데, Hook은 직접 만드는 것도 가능하다.
이 Hook에는 다음과 같은 규칙이 있다.

  • Hook은 React 함수 컴포넌트 내부, 직접 작성한 Hook 내부에서만 호출해야 한다.
    일반 JavaScript 함수에서는 Hook을 호출해서는 안 된다.
  • 최상위에서만 Hook을 호출해야 한다.
    (반복문, 조건문, 중첩된 함수 내에서 Hook을 실행X)

참고 링크: Hook의 개요 - React

profile
프론트엔드 개발자 NH입니다. 시리즈로 보시면 더 쉽게 여러 글들을 볼 수 있습니다!

0개의 댓글