State와 Props

Donggu(oo)·2023년 1월 20일
0

React

목록 보기
11/30
post-thumbnail

1. State


  • state는 컴포넌트 내부에서 관리(함수 내에 선언된 변수처럼)되는 변경이 가능한 값을 말하며, 변해야하는 상태 관리를 해야 할 때 사용한다.

  • state를 정의할 때는 렌더링이나 데이터 흐름에 사용되는 값만 state에 포함시켜야 한다. 그렇지 않은 값은 컴포넌트 인스턴스의 필드로 정의한다.

state가 될 수 있는 조건

  • 부모로부터 props를 통해 전달된다면 state가 아니다.
  • 시간이 지나도 변하지 않는다면 state가 아니다.
  • 컴포넌트 안의 다른 state나 props를 가지고 계산이 가능하다면 state가 아니다.

2. Props


  • 컴포넌트의 속성(property)을 의미한다. props는 성별이나 이름처럼 변하지 않는 외부로부터 전달받은 값으로, 웹 애플리케이션에서 해당 컴포넌트가 가진 속성에 해당한다.

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

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

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

  • 전달받은 props 값이 변하면(업데이트) 리렌더링 된다.

props 예시

  • 빨간색으로 표시되어 있는 부분은 여행할 지역을 나타내고 있다. 모두 모서리가 둥근 사각형 모양에 상단에는 그림이 배경으로 들어가 있고, 하단에는 색깔로 된 배경과 글자가 들어가 있는 형태라는 것을 알 수 있다.
  • 모양만 놓고 보면 모두 동일한 형태를 가지고 있지만 안에 들어있는 그림과 색상, 글자, 거리는 모두 다르다.
  • 예러 개의 하위 컴포넌트에서 동일한 값을 사용해야 하는데 props로 부모 컴포넌트에서 일괄적으로 값을 넘겨주지 않으면 자식 컴포넌트에서 일일히 값을 변경해야 한다.

1) 사용 방법

1-1. 하위 컴포넌트에 전달하고자 하는 값(data)과 속성 정의

  • 기본 구문
    <'자식 컴포넌트명' '속성명(props명, 임의 지정)'  =  { 넘겨줄 값 } />
function Parent() {
  return (
    <div className="parent">
      <h1>I'm the parent</h1>
      // 하위 컴포넌트에 전달할 값, 속성 정의
      <Child text = {"I'm the child"} />
    </div>
  );
};

function Child() {
  return (
    <div className="child"></div>
  );
};

1-2. props를 이용하여 정의된 값과 속성을 전달

function Child(props) {  // props를 Child 함수의 파라미터로 전달
  return (
    <div className="child"></div>
  );
};

1-3. 전달받은 props 렌더링

  • React가 사용자 정의 컴포넌트로 작성한 엘리먼트를 발견하면 JSX 어트리뷰트와 자식을 해당 컴포넌트에 단일 객체로 전달한다. 이 객체를 props라고 한다.
function Parent() {
  return (
    <div className="parent">
      <h1>I'm the parent</h1>
      <Child text = {"I'm the child"} />  // 속성명은 text로 설정
    </div>
  );
};

function Child(props) {
  return (
    <div className="child">
      // JSX를 이용하여 랜더링
      <p>{props.text}</p>  // 전달받은 props 객체의 키 === 부모 컴포넌트에서 설정한 속성명
    </div>
  );
};
  • 아래 예제에서는 다음과 같은 순서로 랜더링 된다.
  1. <Welcome name="Sara" /> 엘리먼트로 root.render()를 호출
  2. React는 {name: 'Sara'}를 props로 하여 Welcome 컴포넌트를 호출
  3. Welcome 컴포넌트는 결과적으로 <h1>Hello, Sara</h1> 엘리먼트를 반환
  4. React DOM은 <h1>Hello, Sara</h1> 엘리먼트와 일치하도록 DOM을 효율적으로 업데이트
const element = <Welcome name="Sara" />;

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(element);

2) Props 객체 구조 분해 할당

  • 부모 컴포넌트에서 자식 컴포넌트로 Props를 구조 분해 할당으로 넘겨줄 수 있다.
  • 객체 구조 분해 할당 형태로 props를 받게 되면 코드를 간결하게 만들 수 있다.
// 부모 컴포넌트
function Parent() {
  return (
    <div className="parent">
      <Child title={"childComponent"} content={"I'm the child"} />
    </div>
  );
};

// props 값을 객체 구조 분해 하여 받고 있는 자식 컴포넌트
function Child({ title, content }) {
  return (
    <div className="child">
      <p>{title}</p>
	  <p>{content}</p>
    </div>
  );
};

3) map으로 list 불러오기

  • 반복되는 li태그를 map을 사용하여 불러오기, 동일한 결과가 나온다.
// 하드코딩한 li태그들
function App() {
  return (
    <ul>
      <li>Menu1</li>
      <li>Menu2</li>
      <li>Menu3</li>
      <li>Menu4</li>
    </ul>
  );
}
// map을 사용하여 불러온 li 태그들
function App() {
  const menus = ['Menu1', 'Menu2', 'Menu3', 'Menu4']
  const menuList = menus.map((menu) =>
    <li key={index}>{menu}</li>
  );

  return (
    <ul>
      {menuList}
    </ul>
  );
}
  • List 컴포넌트(li태그)를 map을 이용하여 반복사용하는 예제(전체 dummyData를 불러오기)
// - App 컴포넌트(메인)
function App() {
  return (
    <div className="App">
      <main>
        <header className="App-header">
          <h1>Test</h1>
        </header>
        {dummyTweets.map((value) =>
          <List message={value} key={value.id} />
        )}
      </main>
    </div>
  );
}
// List 컴포넌트
function List({ message }) {
    return (
        <li className="tweet">
            <div className="tweet__content">
                <div className="tweet__userName">
                    {message.username}
                </div>
                <div className="tweet__message">
                    {message.content}
                </div>
            </div>
        </li>
    );
}
// dummyData
const dummyTweets = [
  {
    id: 1,
    username: 'kimcoding',
    content:
   '모든 국민은 인간으로서의 존엄과 가치를 가지며, 행복을 추구할 권리를 가진다. 모든 국민은 종교의 자유를 
    가진다. 국가는 농·어민과 중소기업의 자조조직을 육성하여야 하며, 그 자율적 활동과 발전을 보장한다. 
    모든 국민은 양심의 자유를 가진다.
    누구든지 체포 또는 구속을 당한 때에는 즉시 변호인의 조력을 받을 권리를 가진다.',
  },
 // ...
];
  • 결과

0개의 댓글