Skip to content

State & Props ​

React에서 데이터를 다룰 때 가장 기본이 되는 개념은 State와 Props다.

  • State는 컴포넌트 내부에서 관리하는 데이터
  • Props는 부모 컴포넌트가 자식 컴포넌트에게 전달하는 데이터

State ​

State는 컴포넌트 내부에서 관리되는 변경 가능한 데이터다.
사용자의 클릭, 입력값, 토글 상태처럼 화면에서 변경될 수 있는 값을 관리할 때 사용한다.

State 값이 변경되면 React는 해당 컴포넌트를 다시 렌더링해 화면을 업데이트한다.

  • 컴포넌트가 현재 가지고 있는 값
  • 사용자 행동에 따라 변경될 수 있는 동적인 데이터
  • 값이 변경되면 화면 업데이트를 발생시키는 데이터

useState Hook ​

React 함수형 컴포넌트에서는 useState Hook을 사용해 State를 관리한다.
useState()를 호출하면 두 개의 요소가 들어있는 배열이 반환된다.

jsx
const state = useState();
console.log(state); // [undefined, ƒ]
  • useState()에 초기값을 전달하지 않으면 첫 번째 값은 undefined가 된다.
  • 두 번째 값은 State 값을 변경할 때 사용하는 함수다.

jsx
[현재 상태 값, 상태 변경 함수]
  • 반환값은 다음과 같은 구조를 가진다. 그래서 보통 배열 구조 분해 할당을 사용해 다음과 같이 작성한다.

jsx
const [state, setState] = useState(initialValue);
  • state: 현재 상태 값
  • setState: 상태를 변경하는 함수
  • initialValue: state의 초기값

jsx
// ex
const [isLogin, setIsLogin] = useState(false);

ex. 로그인 여부를 상태로 관리한다면,
처음에는 로그인하지 않은 상태이므로 false를 초기값으로 설정하고, 로그인 후에는 setIsLogin(true)처럼 상태를 변경할 수 있다.


State를 사용할 때 주의할 점 ​

State는 직접 수정하지 않고, 반드시 상태 변경 함수를 사용해야 한다.

jsx
const [user, setUser] = useState({ name: "짱구", age: 5 });

// 잘못된 예시
user.age = 6;

// 올바른 예시
setUser({ ...user, age: 6 });

React는 상태 변경 함수를 통해 값이 바뀌었는지 감지하고, 필요한 경우 화면을 다시 렌더링한다.
따라서 State를 직접 수정하면 React가 변경을 제대로 감지하지 못할 수 있다.


jsx
setCount((prevCount) => prevCount + 1);

또한 이전 상태값을 기준으로 값을 업데이트해야 할 때는 함수형 업데이트 방식을 사용할 수 있다.
이 방식은 이전 상태값을 안전하게 참조할 수 있기 때문에, 연속적인 상태 변경이 필요한 경우에 유용하다.


🤔 일반 변수가 아닌 State를 사용하는 이유

일반 변수는 값이 변경되어도 React가 그 변화를 감지하지 못하기 때문에 화면이 다시 렌더링되지 않는다.
반면 State는 상태 변경 함수로 값이 변경되면 React가 이를 감지하고 컴포넌트를 다시 렌더링해 변경된 값을 화면에 반영한다.


Props ​

Props는 부모 컴포넌트가 자식 컴포넌트에게 전달하는 데이터다. 컴포넌트는 Props를 통해 외부에서 값을 전달받고, 전달받은 값을 화면에 표시하거나 로직에 사용할 수 있다.

ex. UserProfile 컴포넌트에 사용자 이름을 전달해보면,

jsx
function UserProfile({ name }) {
  return <p>안녕하세요, {name}님!</p>;
}

function App() {
  return <UserProfile name="짱구" />;
}

export default App;
  • App 컴포넌트는 UserProfile 컴포넌트에게 name이라는 Props를 전달
  • UserProfile 컴포넌트는 전달받은 name 값을 사용해 화면에 문장을 출력

Props의 특징 ​

  • Props는 부모 컴포넌트에서 자식 컴포넌트로 전달
    즉, 데이터 흐름은 기본적으로 위에서 아래 방향으로 흐른다.

  • Props는 자식 컴포넌트에서 직접 수정하지 않는다
    자식 컴포넌트는 전달받은 Props를 읽어서 사용할 수 있지만, 그 값을 직접 변경해서는 안 된다.

jsx
function UserProfile({ name }) {
  // name = "훈이"; // 직접 수정하면 안 됨

  return <p>{name}</p>;
}
  • Props 값을 변경해야 한다면, 해당 값을 관리하는 부모 컴포넌트에서 State를 변경한 뒤 다시 Props로 전달해야 한다.

State를 Props로 전달하기 ​

State와 Props는 따로 사용되기도 하지만, 함께 사용되는 경우가 많다.

대표적으로 부모 컴포넌트에서 State를 관리하고, 그 State 값을 자식 컴포넌트에게 Props로 전달하는 방식이다. 부모의 State가 변경되면 변경된 값이 다시 자식 컴포넌트의 Props로 전달되고, 화면도 함께 업데이트된다.

jsx
import { useState } from "react";
import Bulb from "./Bulb";

function App() {
  const [light, setLight] = useState("OFF");

  return (
    <>
      <Bulb light={light} />
      <button
        onClick={() => {
          setLight(light === "ON" ? "OFF" : "ON");
        }}
      >
        {light === "ON" ? "끄기" : "켜기"}
      </button>
    </>
  );
}

export default App;
jsx
const Bulb = ({ light }) => {
  return (
    <div>
      {light === "ON" ? (
        <h1 style={{ backgroundColor: "orange" }}>ON</h1>
      ) : (
        <h1 style={{ backgroundColor: "gray" }}>OFF</h1>
      )}
    </div>
  );
};

export default Bulb;
  • App 컴포넌트는 light State를 관리하고, 이 값을 Bulb 컴포넌트에게 light Props로 전달한다.
  • 버튼을 클릭하면 setLight를 통해 light 값이 "ON" 또는 "OFF"로 변경된다.
  • State가 변경되면 App 컴포넌트가 리렌더링되고, 변경된 light 값이 다시 Bulb의 Props로 전달된다.
  • 그 결과 Bulb는 전달받은 light 값에 따라 ON/OFF 화면을 다르게 보여준다.

리렌더링 ​

React 컴포넌트는 특정 값이 변경되었을 때 다시 렌더링된다. 이를 리렌더링이라고 한다.

  • 컴포넌트가 관리하는 State 값이 변경될 때
  • 부모 컴포넌트로부터 전달받는 Props 값이 변경될 때
  • 부모 컴포넌트가 리렌더링될 때

위 예시에서는 버튼 클릭으로 light State가 변경되고,
이 값이 Bulb 컴포넌트의 Props로 다시 전달되면서 화면이 업데이트된다.