React | 5. 컴포넌트_state

sojung·2021년 2월 4일
0

React

목록 보기
5/8
post-thumbnail

Props

컴포넌트가 사용되는 과정에서 부모 컴포넌트가 설정하는 값이며, 컴포넌트 자신은 해당 props를 읽기 전용으로만 사용할 수 있다. props를 바꾸려며 부모 컴포넌트에서 바꾸어 주어야 한다.

//App.js

import React from "react";
import MyComponent from "./components/component";

function App() {
  return (
    <MyComponent name={"lucy"} favoriteNumber={1}>
      리액트
    </MyComponent>
  );
}

export default App;

App 컴포넌트에서는 My Component를 사용할 때 props를 바꾸어 주어야 값이 변경된다.

  //component.js

import React, { Component } from "react";
import PropTypes from "prop-types";

class MyComponent extends Component {
  static defaultProps = {
    name: "기본 이름",
  };
  static propTypes = {
    name: PropTypes.string,
    favoriteNumber: PropTypes.number.isRequired,
  };

  render() {
    const { name, favoriteNumber, children } = this.props;
    return (
      <div>
        내 이름은 {name} 입니다! <br />
        children값은 {children}입니다.
        <br />
        내가 좋아하는 숫자는 {favoriteNumber}입니다.
      </div>
    );
  }
}

export default MyComponent;

component.js에서는 전달받은 name값을 직접 바꿀 수 없다.

State

컴포넌트 내부에서 바뀔 수 없는 값.

1. 클래스형 컴포넌트 state

//counter.js

import React, { Component } from "react";

class Counter extends Component {
  constructor(props) {
    super(props);
		// state의 초깃값 설정하기
    this.state = {
      number: 0,
    };
  }
  render() {
    const { number } = this.state; // state를 조회할 때는 this.state로 조회한다.
    return (
      <div>
        <h1>{number}</h1>
				// onClick을 통해 버튼이 클릭되었을 때 호출할 함수를 지정한다.
				<button
				// this.setState를 사용하여 state에 새로운 값을 넣을 수 있다.
          onClick={() => {
            this.setState({ number: number + 1 });
          }}
        >
          +1
        </button>
      </div>
    );
  }
}

export default Counter;
  • constructor 메서드

    컴포넌트에 state를 설정할 때 constructor 메서드 사용

    클래스형 컴포넌트에서 constructor를 작성할 때는 반드시 super(props)를 호출해 주어야 한다. 이 함수가 호출되면 현재 클래스형 컴포넌트가 상속하고 있는 리액트 Component 클래스가 지닌 생성자 함수를 호출해준다.

  • this.state

    this.state에 초깃값 설정해주었다. 컴포넌트의 state는 객체 형식이어야 한다.

  • render 함수

    • 현재 state를 조회할 때는 this.state를 조회한다.
    • button 안에 onClick이라는 값을 props로 넣어주었는데, 이는 버튼이 클릭될 때 호출시킬 함수를 설정할 수 있게 해준다. → 이벤트를 설정하였다.
    • 이벤트로 설정할 함수를 넣어 줄 때는 화살표 함수 문법을 사용해야한다.
    • 함수 내부에서는 this.setState라는 함수를 사용했는데, 이 함수가 state 값을 바꿀 수 있게 해준다.
//App.js

import React from "react";
import Counter from "./components/counter";

function App() {
  return <Counter></Counter>;
}

export default App;

  • 아래의 코드는 위의 코드와 같은 코드이다. → 가장 좋은 코드인 것 같다.
//counter.js

import React, { Component } from "react";

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = {
      number: 0,
    };
  }

  handleIncrement = () => {
    this.setState({ number: this.state.number + 1 });
  };

render() {
  const { number } = this.state;
  return (
    <div>
      <h1>{number}</h1>
      {/* <button
              onClick={() => {
                this.setState({ number: number + 1 });
              }}
            >
              +1
            </button> */}
      <button onClick={this.handleIncrement}>+1</button>
    </div>
  );
}
}

export default Counter;
  • 함수를 호출해주었다.
  • 함수 호출해서 render() 위로 올라갈 때는 this.state.number로 써줘야 작동된다....? 왜....?
  • const { number } = this.state; 라고 정의를 해 주었기 때문에 밑에 {number} 만 써도 된다. 아니면 두 코드를 한 꺼번에 써서 { this.state.number } 라고 써도 된다.

state 객체 안에 여러 값이 있을 때

//counter.js

import React, { Component } from "react";

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = {
      number: 0,
      fixedNumber: 0,
    };
  }

  render() {
    const { number, fixedNumber } = this.state;
    return (
      <div>
        <h1>{number}</h1>
        <h2>바뀌지 않는 값:{fixedNumber}</h2>
        <button
          onClick={() => {
            this.setState({ number: number + 1 });
          }}
        >
          +1
        </button>
        <button onClick={this.handleIncrement}>+1</button>
      </div>
    );
  }
}

export default Counter;

state를 constructor에서 꺼내기

state의 초깃값을 지정하기 위해 constructor 메서드를 선언해주었는데, 또 다른 방식으로 state의 초깃값을 지정해 줄 수 있다.

//counter.js

class Counter extends Component {
  state = {
    number: 0,
    fixedNumber: 0,
  };

더 간단하다.

this.setState에 객체 대신 함수 인자 전달하기

//counter.js

<button
	onClick={() => {
  this.setState({ number: number + 1 });
	this.setState({ number: this.state.number + 1 });
  }}
>
	+1
</button>

2씩 증가하지 않는다. this.setState를 사용한다고 해서 state 값이 바로 바뀌지는 않기 때문이다.


//counter.js

<button
	onClick={() => {
		this.setState((prevState) => {
			return {
				number: prevState.number + 1,
			};
		});
		this.setState((prevState) => ({
			number: prevState.number + 1,
		}));
	}}
>
	+1
</button>
  • prevState는 기존 상태.
  • 잘 모르겠다.....

this.setState가 끝난 후 특정 작업 실행하기

//counter.js

<button
	onClick={() => {
	  this.setState({ number: number + 1 }, () => {
			console.log("방금 setState가 호출되었습니다.");
			console.log(this.state);
		});
	}}
>
	+1
</button>

2. 함수형 컴포넌트에서 useState 사용하기

배열 비구조화 할당

const array = [1, 2];
const [one, two] = array;

array 안에 있는 값을 one과 two에 담아주는 코드

useState 사용하기

//say.js

import React, { useState } from "react";

const Say = () => {
  const [message, setMessage] = useState("");
  const onClickEnter = () => setMessage("안녕하세요!");
  const onClickLeave = () => setMessage("안녕히 가세요!");

  return (
    <div>
      <button onClick={onClickEnter}>입장</button>
      <button onClick={onClickLeave}>퇴장</button>
      <h1>{message}</h1>
    </div>
  );
};

export default Say;
  • useState 함수의 인자에는 상태의 초깃값을 넣어준다. 클래스형 컴포넌트에서는 state 초깃값은 객체 형태를 넣어 주어야 하는데, useState에서는 반드시 객체가 아니어도 된다.
  • 함수를 호출하면 배열이 반환된다. 배열의 첫 번째 원소는 현재 상태이고, 두 번째 원소는 상태를 바꾸어주는 함수이다. 이 함수를 세터(setter) 함수라고 부른다.
  • 배열 비구조화 할당을 통해 이름을 자유롭게 정할 수도 있다. 현재는 message와 setMessage라고 이름을 설정하였다.
//App.js

import React from "react";
import Say from "./components/say";

function App() {
  return <Say></Say>;
}

export default App;

한 컴포넌트에서 useState 여러 번 사용하기

//say.js

import React, { useState } from "react";

const Say = () => {
  const [message, setMessage] = useState("");
  const onClickEnter = () => setMessage("안녕하세요!");
  const onClickLeave = () => setMessage("안녕히 가세요!");

  const [color, setColor] = useState("black");

  return (
    <div>
      <button onClick={onClickEnter}>입장</button>
      <button onClick={onClickLeave}>퇴장</button>
      <h1 style={{ color }}>{message}</h1>
      <button style={{ color: "red" }} onClick={() => setColor("red")}>
        Red
      </button>
      <button style={{ color: "green" }} onClick={() => setColor("green")}>
        Green
      </button>
      <button style={{ color: "blue" }} onClick={() => setColor("blue")}>
        Blue
      </button>
    </div>
  );
};

export default Say;

state를 사용할 때 주의 사항

  • 클래스형 컴포넌트든 함수형 컴포넌트든 state를 사용할 때는 state값을 바꾸어야 할 때는 setState 혹은 useState를 통해 전달받은 세터 함수를 사용해야 한다.

정리

  • props와 state는 둘 다 컴포넌트에서 사용하거나 렌더링할 데이터를 담고 있으므로 비슷해 보이지만,
  • props는 부모 컴포넌트가 설정하고, state는 컴포넌트 자체적으로 지닌 값으로 컴포넌트 내부에서 값을 업데이트 할 수 있다.
  • props를 사용한다고 해서 값이 무조건 고정적이지는 않다. 부모 컴포넌트의 state를 자식 컴포넌트의 props로 전달하고, 자식 컴포넌트에서 특정 이벤트가 발생할 때 부모 컴포넌트의 메서드를 호출하면 props도 유동적으로 사용할 수 있다.
profile
걸음마코더

0개의 댓글