3장 - Props and State

기운찬곰·2020년 9월 5일
1

React

목록 보기
2/5
post-thumbnail

오늘 내용을 아래 그림 하나로 요약할 수 있겠다.

💻 출처 : https://ooeunz.tistory.com/135


Component and Props

Parent and Child Components

App.js (부모 컴포넌트)

import React from "react";
import Hello from "./Hello";

function App() {
  return <Hello name="기운찬곰" color="blue" />;
}

export default App;

Hello.js (자식 컴포넌트)

import React from "react";

function Hello({ name, color }) {
  return <div style={{ color }}>{name}</div>;
}

export default Hello;

부모 컴포넌트인 App에서 자식 컴포넌트인 Hello를 호출 할 수 있다.

그리고 부모에서 자식에게 값을 넘겨줄 수 있는데 자식컴포넌트는 이를 props 형태로 받아오게 된다. 원래 정석대로 하면 props를 받고 props.name, props.color로 써야 하는데 일반적으로 비구조할당을 통해 바로 변수로 받는 것을 선호한다.

defaultProps

이번엔 부모에서 name 값을 넘겨주지 않는다면 어떻게 될까? 🤔 에러는 나지 않지만 undefined 값을 가지게 된다. 만약 name 값을 넘기지 않았을 때 기본 값(default)으로 대체하고 싶다면 defaultProps를 사용하면 된다.

// App.js
function App() {
  return <Hello color="blue" />; // name props를 넘겨지 않음
}
// Hello.js
import React from "react";

function Hello({ name, color }) {
  console.log(name); // name이 undefined일 때 default 값이 대신 들어감
  return <div style={{ color }}>{name}</div>;
}

Hello.defaultProps = {
  name: "이름없음", // default 값 설정
};

export default Hello;

children

태그 사이에다가도 값을 넘겨줄 수 있다. 이 경우는 보통 HTML 태그를 넘겨줄 때 많이 쓰인다. 자식은 태그 사이 값을 받을때 children을 통해 받을 수 있다.

// App.js
function App() {
  return (
    <Hello color="blue">
      <p>태그 사이 값을 통째로 넘겨주는건 children</p>
    </Hello>
  );
}
// Hello.js
function Hello({ name, color, children }) { // ✅
  return (
    <>
      <div style={{ color }}>{name}</div>
      {children}
    </>
  );
}


State

리액트에서는 컴포넌트 내부에 바뀔 수 있는 값이 있다면 state를 사용해야 한다. 그래야 리액트가 상태변화를 알아차리고 리렌더링 해주기 때문이다.

EX1. counter status management

간단하게 카운트를 만들어서 state 관리에 대해 알아보는 실습을 해보겠다.

// Counter.js
import React, { useState } from "react";

function Counter() {
  const [number, setNumber] = useState(0);

  const onIncrease = () => {
    setNumber(number + 1);
  };

  const onDecrease = () => {
    setNumber(number - 1);
  };

  return (
    <>
      <h1>{number}</h1>
      <button onClick={onIncrease}>+1</button>
      <button onClick={onDecrease}>-1</button>
    </>
  );
}

export default Counter;

여기서는 함수형 컴포넌트에서의 useState를 사용했다.

  • useState를 통해 초기값을 설정해주고 배열 비구조할당을 통해 number, setNumber를 받는다. number는 getter라고 보면 되고, setNumber는 setter라고 보면 된다.
  • onIncrease()와 onDecrease() 이벤트 처리 함수를 만들어 준다.
  • button에서 onClick 이벤트가 발생하면 onIncrease 또는 onDecrease가 호출되도록 만들어주면 끝이다. 주의할 점은 onIncrese 괄호를 쓰면 안된다. 이렇게 되면 처음 렌더링될때 호출버리는 문제가 발생한다.

EX2. input status management

import React, { useState } from "react";

function InputForm() {
  const [inputs, setInputs] = useState({
    name: "",
    email: "",
  });

  const { name, email } = inputs;

  const onChange = (e) => {
    const { name, value } = e.target;

    setInputs({
      ...inputs,
      [name]: value,
    });
  };
  const onReset = () => {
    setInputs({
      name: "",
      email: "",
    });
  };

  return (
    <div>
      <input name="name" placeholder="이름" onChange={onChange} value={name} />
      <input
        name="email"
        placeholder="이메일"
        onChange={onChange}
        value={email}
      />
      <button onClick={onReset}>초기화</button>
      <hr />
      <div>
        <b>: </b>
        {name} ({email})
      </div>
    </div>
  );
}

export default InputForm;

아까보다는 조금 복잡하고 관리해야할 상태도 많아졌다.

  • useState를 두 번 만들어줘서 관리하는 대신 객체로 관리를 해줄 수 있다.
  • e.target.name을 해주면 input에 name을 설정해준 값이 변했을때 그 name을 알 수 있다. 쉽게말해 name이 email이라면 email 폼이 변화했을때 e.target.name을 통해 email이라는걸 알 수 있다는 소리가 된다. e.target은 이벤트가 발생하는 DOM을 가리킨다고 보면 될 것이다.

Immutable maintenance

리액트에서 객체를 업데이트하기 전에 지켜줘야할 규칙이 있다. 바로 불변성 유지. 즉, 기존 객체를 수정하면 안되고 새로운 객체를 넣어줘야 한다. 그래야 리액트가 상태변화를 감지해서 변화된 부분을 리렌더링 할 수 있기 때문이다.

불변성을 유지하기 위한 방법으로는 여러가지가 있을 수 있는데 아래는 대표적인 2가지 방법을 소개한다.

  • 첫번째 방법은 (...) spread 연산을 이용하는것이다. 쉽게 말해 기존 객체 내용을 안에 펼쳐주고, 변경하고자 하는 속성과 값을 밑에다가 써주면 새로운 객체가 반환되는 동작을 하게 된다.
  • 두번째 방법으로는 map, filter, concat 등 불변성을 유지하는 대표적인 배열 내장함수를 사용한다. 원본 배열을 해치지 않고 새로운 배열을 반환해준다. 반대로 push, find, splice는 기존 값을 건드리는 배열 내장함수이다.

profile
배움을 좋아합니다. 새로운 것을 좋아합니다.

0개의 댓글