[React] State & Props

jeyoon·2021년 5월 5일
1

🐥 Props vs. State

  • props는 외부로부터 전달받은 값
  • state는 내부에서 변화하는 값

Props

  • 컴포넌트의 속성(property)을 의미함
    외부로부터 전달받은 변하지 않는 값으로, 웹 어플리케이션에서 해당 컴포넌트가 가진 속성을 의미

  • 상위 컴포넌트로부터 전달받은 값
    React 컴포넌트는 JavaScript 함수 또는 클래스 형태로, props를 함수의 전달인자(arguments)처럼 전달받아 이를 기반으로 화면에 어떻게 표시되는지를 나타내는 React 엘리먼트를 반환한다. 따라서, 컴포넌트가 최초 렌더링될 때에 화면에 출력하고자 하는 데이터를 담은 초기값으로 사용할 수 있다.

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

  • props는 읽기 전용
    props는 외부로부터 전달받아 변하지 않는 값이기 때문에, 함부로 변경될 수 없는 읽기 전용(read-only) 객체이다.

읽기 전용 객체가 아니라면? props를 전달 받은 하위 컴포넌트 내에서 props를 직접 수정 시 props를 전달한 상위 컴포넌트의 값에 영향을 미칠 수 있게 된다. 즉, 개발자가 의도하지 않은 side effect가 생기게 되고 이는 React의 단방향, 하향식 데이터 흐름 원칙에 위배된다.

How to use props

props를 사용하는 방법은 아래와 같이 3단계로 나눌 수 있다.

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

위 단계에 맞추어 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 text={"I'm the eldest child"} />

이제 <Parent> 컴포넌트에서 전달한 "I'm the eldest child"라는 문자열을 <Child> 컴포넌트에서 받아보자. 함수에 인자를 전달하듯이 React 컴포넌트에 props를 전달하면, 이 props 가 필요한 모든 데이터를 가지고 <Child> 컴포넌트로 가게 된다.
props를 렌더링하려면 JSX 안에 직접 불러서 사용하면 된다. props는 객체이므로 JavaScript 에서 객체의 value 에 접근할 때와 동일하게 props 의 value 또한 dot notation 으로 접근할 수 있다. 아래와 같이 props.text를 JSX에 중괄호와 함께 작성하면 잘 작동한다.

function Child(props) {
  return (
    <div className="child">
      <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

  • 살면서 변할 수 있는 값
  • 컴포넌트의 사용중 컴포넌트 내부에서 변할 수 있는 값

State Hook (useState)

state를 다루는 특별한 함수, useState의 사용 방법과 작동 방식에 대해 알아보자.

  • 먼저 useState 를 컴포넌트 안에서 호출해준다. useState 를 호출한다는 것은 "state" 라는 변수를 선언하는 것과 같으며, 이 변수의 이름은 아무 이름으로 지어도 된다. 일반적으로 변수는 함수가 끝날 때 사라지지만, state 변수는 React 에 의해 함수가 끝나도 사라지지 않는다.
function CheckboxExample() {
// 새로운 state 변수 isChecked를 선언
  const [isChecked, setIsChecked] = useState(false);
  • useState 를 호출하면 배열을 반환하는데, 배열의 첫 번째 요소는 현재 state 변수이고, 두 번째 요소는 이 변수를 갱신할 수 있는 함수이다. useState 의 인자에는 state의 초기값을 넣는다.
    위의 예시에서 isChecked 변수의 값은 setIsChecked 함수를 호출하여 갱신할 수 있다.
  • state 변수에 저장된 값은 JSX 안에 직접 불러서 사용하면 된다. 여기서는 isChecked 가 boolean 값을 가지기 때문에 true or false 여부에 따라 다른 결과가 보이도록 삼항연산자를 사용한다.
<span>{isChecked ? "Checked!!" : "Unchecked"}</span>
  • state 를 갱신하려면 변수를 갱신할 수 있는 함수인 setIsChecked 를 호출한다. 다만, 이 함수를 직접 호출하는 것이 아니라 사용자의 입력값을 처리하는 onChange 이벤트를 이용한다.

  • 사용자가 입력을 하면
    ➡️ onChange 이벤트가 이벤트 핸들러 함수 handleChecked 를 호출함
    ➡️ 이 함수가 setIsChecked 를 호출함
    ➡️ setIsChecked 가 호출된 결과에 따라 isChecked 변수 갱신
    ➡️ React 는 새로운 isChecked 변수를 CheckboxExample 컴포넌트에 넘겨 해당 컴포넌트를 다시 렌더링

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

  const handleChecked = (event) => {
    setIsChecked(event.target.checked);
  };

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

이처럼 useState 를 이용하면 컴포넌트 내의 state를 손쉽게 다룰 수 있다.

이벤트 처리

React의 이벤트 처리(이벤트 핸들링) 방식은 DOM의 이벤트 처리 방식과 유사하다. 단, 몇가지 문법 차이가 있다.

  • React 에서 이벤트는 소문자 대신 카멜 케이스(camelCase)를 사용한다.
  • JSX를 사용하여 문자열이 아닌 함수로 이벤트 처리 함수(이벤트 핸들러; Event handler)를 전달한다.

예를 들어 HTML에서 이벤트 처리 방식이 아래와 같다면,

<button onclick="handleEvent()">Event</button>

React의 이벤트 처리 방식은 아래와 같다.

<button onClick={handleEvent}>Event</button>

onChange

  • <input> <textarea> <select> 와 같은 form 엘리먼트는 사용자의 입력값을 제어하는데 사용된다. React 에서는 이러한 변경될 수 있는 입력값을 일반적으로 컴포넌트의 state 로 관리하고 업데이트한다.
  • 아래 예시 코드에서 <input>에 변경이 발생(onChange)하면, handleChange 함수가 호출되고, handleChange함수는 setName을 통해 입력된 값(e.target.value) 으로 name의 상태를 갱신한다.
function NameForm() {
  const [name, setName] = useState("");

  const handleChange = (e) => {
    setName(e.target.value);
  }

  return (
    <div>
      <input type="text" value={name} onChange={handleChange}></input>
      <h1>{name}</h1>
    </div>
  )
};

onClick

  • onClick 이벤트는 사용자가 클릭이라는 행동을 하였을 때 발생하는 이벤트
  • 버튼이나<a> tag 를 통한 링크 이동 등과 같이 주로 사용자의 행동에 따라 애플리케이션이 반응해야 할 때에 자주 사용하는 이벤트이다.
function NameForm() {
  const [name, setName] = useState("");

  const handleChange = (e) => {
    setName(e.target.value);
  }

  const handleClick = () => {
    alert(name);
  };
  
  return (
    <div>
      <input type="text" value={name} onChange={handleChange}></input>
      <button onClick={handleClick}>Button</button>
      // 함수 자체를 전달해야 함 (호출 결과가 아닌)
      <h1>{name}</h1>
    </div>
  );
};

0개의 댓글