• [React] React Props와 State

    2023. 5. 4.

    by. 지은이: 김지은

    728x90

    1. Props(properties)란?

    부모 컴포넌트에서 자식 컴포넌트로 원하는 값을 넘겨줄 때 사용하는 수단으로 주로 컴포넌트의 '재사용'을 위해 사용한다.

    넘겨줄 땐 변수, 함수, 객체, 배열 등 자바스크립트 요소라면 제한이 없다.

     

    네이버를 예시로 들면, 위 버튼들은 비슷한 모양을 가지고 있다.

     

    이렇게 반복되어있는 버튼들은 공통된 부분을 하나의 컴포넌트로 추상화해서 여러곳에서 재사용될 수 있도록 설계할 수 있다.

    하지만 저 버튼들은 모양만 비슷하고 클릭했을 때 각자 다르게 동작하기 때문에

    각 버튼이 다르게 동작할 수 있도록 필요한 정보를 props를 통해 값을 전달해서 각 요소들이 개별적으로 동작하도록 만들 수 있다.

     

    2. Props 사용하기

    컴포넌트 생성

    import "./Button.css";
    
    const Button = () => {
      return <button className="button">클릭</button>;
    };
    
    export default Button;

     

    컴포넌트 사용

    import Button from "./Button";
    
    const App = () => {
      return (
        <div>
          <Button />
          <Button />
          <Button />
        </div>
      );
    };
    
    export default App;

    이렇게 버튼이라는 컴포넌트를 만들긴 했지만, 버튼안에 표시되는 클릭이라는 글자를 버튼마다 다르게 설정하고 싶어졌다.

     

    const App = () => {
      return (
        <div>
          <Button text="메일" />
          <Button text="카페" />
          <Button text="블로그" />
        </div>
      );
    };

    부모 컴포넌트에서 자식 컴포넌트로 전달해주고 싶은 값을 넣어주는 걸 props라고 한다. (속성의 이름은 다양하게 설정 가능)

    그렇다면 부모 컴포넌트에서 받은 저 텍스트는 자식 컴포넌트에서 어떻게 사용할 수 있을까?

     

    const Button = (props) => {
      console.log(props);
      return <button className="button">{props.text}</button>;
    };

    자식 컴포넌트인 버튼 컴포넌트에 매개변수로 props라는 값을 받아오면 된다.

     

    이 매개변수는 일반적으로 props라는 이름으로 선언하는데

    이 props를 콘솔에 찍어보면 아래처럼 프로퍼티가 객체에 묶여서 보관되고 있다.

     

    그래서 부모 컴포넌트에서 받은 텍스트를 props.text를 통해 접근할 수 있어 글자가 각각 다르게 출력할 수 있다.

     

    props로 텍스트만 전달할 수 있는게 아니고 요소 자체를 전달할 수 있다.

    const App = () => {
      return (
        <div>
          <Button text="메일">
            <div>Hello</div>
          </Button>
        </div>
      );
    };

    버튼 컴포넌트 자식으로 `<div>Hello</div>`가 포함되어있는데 이건 버튼 컴포넌트에서 props.children으로 접근할 수 있다.

     

    비구조화 할당

    props 내부의 값을 조회할 때마다 앞에 props를 붙여줘야하는게 번거롭다면, props객체를 분해할 수 있다.

    const Button = ({ text }) => {
      return <button className="button">{text}</button>;
    };

    { text }는 props 객체로부터 text 프로퍼티를 꺼내서 변수로 사용하는 것. 이게 바로 비구조화 할당이라고한다.

     

    3. State

    React에서 State는 컴포넌트가 관리하는 상태나 데이터라고 생각하면된다.

    개발자가 의도한 동작에 의해 변할 수도 있고, 사용자의 입력에 따라 새로운 값으로 변경될 수도 있다.

    State가 변경되면 React가 자동으로 컴포넌트를 재랜더링 한다.

    아래 예시를 통해서 State를 사용해보자!

     

    4. State 사용하기

    버튼을 클릭하면 카운트 하는 앱 만들기

    import { useState } from 'react'; // 최상단에 React 패키지로부터 useState함수 import 하기
    
    function App() {
      const [count, setCount] = useState(0); // State 선언, 구조분해할당 (초기값 0 생략가능)
      return (
        <div className="App">
          <span>{count}회 클릭하였습니다.</span>
          <button
            onClick={() => {
              setCount((current) => {
                return current + 1;
              });
            }}
          >
            클릭
          </button>
        </div>
      );
    }

    useState는 React의 상태를 관리하기 위한 함수로 import해서 불러오도록 한다.

    컴포넌트 안에 useState()를 호출하면 새로운 state를 생성하며 useState함수는 배열을 반환한다.

    이 배열의 첫번째 요소는 현재 상태를, 두번째 요소는 상태를 업데이트 하는 함수

    그래서 count는 현재 상태를 나타내며, setCount는 상태를 업데이트 할 수 있는 함수, count에는 초기값인 0이 들어가있다.

     

    여기서 중요한 점은 State값은 직접 변경하면 안되는데

    만약 직접 변경 시 컴포넌트를 다시 렌더링할 타이밍을 알아치리지 못하기 때문에 setState 함수를 이용해 값을 변경해야 한다.

     

    이제 버튼을 클릭했을 때 카운트가 되게 하기 위해서 setState함수를 호출하고 이전 상태를 받아와서 그 값을 기반으로 새로운 상태를 설정했다.

    setCount 안에 함수를 넣었는데 setCount(count + 1)처럼 현재 상태에 직접 상태를 변경하면,

    React가 새로운 상태값이 변경되었는지 여부를 판단하기 어려울 수 있다.

     

     

    이쯤에서 생각해볼 수 있는것.

    🔎  왜 변수가 아니라 state로 값을 변경해야할까?

    let count = 0;
    ...
    <span>{count}회 클릭하였습니다.</span>
    <button
      onClick={() => {
        count = count + 1;
      }}
    >

    여기서 우리가 기대하는 건 버튼을 클릭했을 때 숫자가 카운트되어야하지만 실제로는 화면에 업데이트 되지 않는다.

    리액트 컴포넌트가 렌더링되기 위해선 자기가 가지고 있는 state가 업데이트 되어야하는데

    변수를 사용해서 값을 변경하는 것은 컴포넌트의 상태가 업데이트 되었다는 것을 알리지 않기 때문에, 리렌더링이 발생하지 않는다.

    그래서 동적인 데이터를 관리하기 위해선 state를 사용해야한다.

     

    5. State 만들 때 주의사항

    상태를 변경할 때 주의해야할 점은 React에서 상태를 업데이트 할 때 불변성을 유지하는 것.

     

    객체나 배열로 이루어진 state의 일부 값만 변경할 땐 객체나 배열을 직접 수정하면 안된다는 것

    만약 직접 수정 시 안에 내용은 변경되었지만 객체, 배열 자체가 변경된 것이 아니기 때문에 React가 State 변경을 감지하지 못한다.

    그래서 원래의 state를 복제 후 변경하여야 컴포넌트가 재랜더링 된다.

    const [user, setUser] = useState({ name: "민수", grade: 1 });
    
    setUser((current) => {
        const newUser = { ...current }; // 기존 useer 객체 복제해서 새로운 객체 생성
        newUser.grade = 2;
        return newUser;
    }

     

    🔎 Props와 State

    둘 다 자바스크립트 객체이지만,
    Props는 읽기전용이고 컴포넌트에 전달, State는 데이터 변경 가능하며 컴포넌트 안에서 관리
    또한 리액트의 컴포넌트는 자신이 관리하는 state값이 변경되거나 props의 값이 바뀔 때 리렌더링이 된다.

     

     

    'React, Next' 카테고리의 다른 글

    [React] React로 TodoList 만들기  (0) 2023.05.09
    [React] 스타일드 컴포넌트(styled-components)  (0) 2023.05.08
    [React] React 이벤트 처리  (0) 2023.05.06
    [React] React Hooks  (0) 2023.05.05
    [React] 리액트(React)란?  (0) 2023.05.02

    댓글