04. State 와 Props

State 와 Props 를 이용하여 Component 를 구성합니다

들어가기전

기존의 jQuery 와 다르게 React 에서는 DOM 에 직접적인 접근을 하여 DOM을 제어하지 않습니다. 그 대신 State 라는 상태 값들을 이용하여 DOM 을 관리하고 변화시킵니다. State 는 내가 가진 값 ,Props 는 누구로부터 받는 값입니다. 보통 부모 component 또는 뒤에서 배울 글로벌하게 상태를 관리 할 수 있게 도와주느 상태머신(Redux, Mobx, Context API 등..) 입니다.

실습

프로젝트는 초기 세팅 상태로 진행되어집니다. +@ 로 이제는 styled-component 를 이용하기 때문에 App.css 파일이 필요없습니다.

Todo List 를 구성하려고합니다. 각 Todo 의 데이터 구조는 아래와 같습니다.

const Todo = {
  id: Date.now(), // 고유한 값을 주기 위해 사용합니다
  text: '리액트 공부하기',
  isDone: false // 완료 여부
}

Todo List 를 담을 State 를 추가합니다. State 를 추가하는 방법은 2 가지가 있습니다.

컴포넌트를 만드는 방법

State 를 알아보기전 Component 를 만드는 방법에 대해서 먼저 알아보려고합니다. Component 는 Class Component 와 Functional Component 2 가지의 종류가 있습니다. 일반적으로 가장 많이 쓰이던 것이 아래에 있는 Class Component 였습니다.

class App extends React.Component {} 
or 
class App extends React.PureComponent

React Hooks 라는 것이 나오면서 Class Component 보다는 Functional Component 가 더 많이 쓰이고 있는 추세입니다. 아래와 같이 일반적인 function 같이 생긴 Component 들이 Functional Component 입니다.

function App() {}

State

Class 와 Functional Component 는 State 를 선언하는 방법이 다릅니다. Class Component 부터 알아보도록 하겠습니다.

// App.js 

import React from 'react';

class App extends React.Component {
  state = {
    todos: [
      {
        id: Date.now(),
        text: '리액트 공부하기',
        isDone: false
      }
    ]
  }
  render () {
    return (
      <div>{JSON.stringify(this.state.todos)}</div>
    )
  }
}
export default App;

위의 코드에서 보시면 state = {} 와 같이 state 를 선언하는 것을 확인 할 수 있습니다. 선언된 state 는this.state 로 접근 할 수 있습니다. 이 처럼 내가 가진 data 값을 State 라고 표현합니다.

하지만 Functional Component 에서는 state = {} 와 같은 표현을 사용 할 수 없습니다. Hooks 라는 것을 이용하여 State 를 선언합니다.

Hooks 에는 많은 종류의 Hook 들이 있습니다. 우리가 지금 하고자 하는것은 State 를 선언하는 것이기 때문에 useState 라는 Hook 만 이용해보겠습니다.

useState 는 아래와 같이 사용합니다.

const [state name, set state] = useState(Initial value)

위의 사용법을 바탕으로 Class Component 에서 사용한 State 와 같이 구성을 해보겠습니다.

// App.js 

import React, { useState } from 'react';

function App (){
  const [todos, setTodos] = useState([
    {
      id: Date.now(),
      text: '리액트 공부하기',
      isDone: false
    }
  ])
  
  return (
    <div>{JSON.stringify(todos)}</div>
  )
}
export default App;

좀 더 간단해보이지 않나요 ?

Props

이번에는 Props 에 대해서 학습해보겠습니다. 일단 Header Component 를 만들어보겠습니다.

// src/components/header.js

import React from 'react'

class Header extends React.Component {
  render () {
    return (
      <div>
        Header
      </div>
    )
  }
}

export default Header

App.js 에서 Header Component 를 불러옵니다.

// App.js

import React from 'react'
import Header from './components/header'

class App extends React.Component {
  render () {
    return (
      <div>
        <Header />
      </div>
    )
  }
}

export default App

하고자 하는것을 결론부터 말씀드리면 App.js 즉 부모 Component 에서 state 로 title 값을 가지고 있고, 이 값을 자식 Component 인 Header 에게 Props 로 전달하고자 합니다.

먼저 App.js 에 state 를 추가하겠습니다.

// App.js

import React from 'react'
import Header from './components/header'

class App extends React.Component {
  state = {
    title: 'Props 알아보기'
  }
  
  render () {
    return (
      <div>
        <Header />
      </div>
    )
  }
}

export default App

그리고 해당 state 값을 Header 에게 넘겨줍니다.

// App.js

<Header title={this.state.title} />

이렇게 되었을 때 Header 입장에서 저 title 값은 Props 라는 것은 부모로부터 받은 값 즉 Props 라는 것으로 판단되어집니다.

그러면 넘겨준 title 값을 Header 에서 받아보겠습니다.

// src/components/header.js

import React from 'react'

class Header extends React.Component {
  constructor(props) { // props 에 접근하기 위해서 필요합니다.
    super(props)
  }
  render () {
    console.log(this.props)
    return (
      <div>
        Header
      </div>
    )
  }
}

export default Header

this.props 를 이용하여 props 에 접근 할 수 있습니다.

// src/components/header.js

import React from 'react'

class Header extends React.Component {
  constructor(props) {
      super(props)
  }
  render () {
    return (
      <div>
        <h1>{this.props.title}</h1>
      </div>
    )
  }
}

export default Header

Functional Component Props

Functional Component 에서는 Props 를 받는 방법이 다릅니다.

// src/components/header.js

import React from 'react'

function Header(props) {  
    console.log(props) // { title: 'Props 알아보기'}
    const { title } = props // 또는 이런식으로 접근이 가능합니다.
    return (
        <div>
          {props.title}
          {title}
        </div>
    )
}

export default Header

function 의 인자값으로 Props 가 넘어오기 때문에 위처럼 접근 할 수 있습니다. 또는 해체 할당자를 이용하여 아래와 같이 접근 할 수 있습니다.

function Header({ title }) { // ... }

Props 를 이용하여 Styled-Component 만들어보기

Styled-Component 도 하나의 Component 입니다. 여러가지 값을 Props 로 넘겨주며 다양하게 Component 를 구성할 수 있습니다.

높이, 넓이, 색상 값을 외부에서 받아 구성하는 Box Component 를 만들어보겠습니다. App.js 에 Box 를 만들기 위한 State 를 추가합니다.

// App.js 

import React from 'react'

class App extends React.Component {
  state = {
    wdith: 100,
    height: 100,
    color: '#00eaff'
  }

  render () {
    return (
      <div></div>
    )
  }
}

export default App

그 후 Box Component 를 만들어보겠습니다. Box 는 넓이, 높이, 색상을 Props 로 받습니다. Functional Component 에서 해체 할당으로 Props 를 받았던 것 처럼 여기서도 비슷하게 해체할당으로 받을 수 있습니다.

넓이, 높이 값이 넘어오지 않는다면 기본적으로 100px 으로 색상이 넘어오지 않는다면 하얀색으로 설정합니다.

// App.js

const Box = styled.div`
  width: ${({ width }) => width || 100}px;
  height: ${({ height }) => height || 100}px;
  background-color: ${({ color }) => color || '#fff'};
`

이제 State 를 Box Component 에게 넘겨주면 됩니다.

// App.js

import React from 'react'
import styled from 'styled-components'

const Box = styled.div`
  width: ${({ width }) => width || 100}px;
  height: ${({ height }) => height || 100}px;
  background-color: ${({ color }) => color || '#fff'};
`

class App extends React.Component {
  state = {
    wdith: 100,
    height: 100,
    color: '#00eaff'
  }

  render () {
    const { wdith, height, color } = this.state 

    return (
      <div>
        <Box wdith={wdith} height={height} color={color} />
      </div>
    )
  }
}

export default App

위처럼 Props 를 이용하면 다양하게 Style 을 적용할 수 있습니다.

이 처럼 나의 값은 State, 외부로부터 전달 받은 값은 Props 라고 부릅니다.

Last updated