세현's 개발로그

[React] State와 Props 본문

React

[React] State와 Props

SarahPark 2023. 4. 10. 02:59

◈ State란?

상태란 계속해서 동적으로 변화하는 특정 상태다. 상태에 따라 각각 다른 동작을 한다.

컴포넌트의 테마처럼 계속 바뀌는 값이 동적인 데이터이고, 상태를 바꾸는 등의 관리는 이걸 가진 컴포넌트가 직접 관리하게 된다.

 

◈ useState

+ 버튼을 누르면 숫자가 증가하고, - 버튼을 누르면 숫자가 감소하는 Counter 기능을 만들어보자.

Counter.js

import React, { useState } from "react";

const Counter = () => {
  const [count, setCount] = useState(0);
  const onIncrease = () => {
    setCount(count + 1);
  }
  const onDecrease = () => {
    setCount(count - 1);
  }

  return (
    <div>
      <h2>{count}</h2>
      <button onClick={onIncrease}>+</button>
      <button onClick={onDecrease}>-</button>

    </div>
  );
}

export default Counter;

App.js

import MyHeader from './MyHeader';
import Counter from './Counter'


function App() {

  return (
    <div>
      <MyHeader/>
      <Counter/>

    </div>
  );
}

export default App;

어색한 문법들이 많을 것이다. 천천히 살펴보자.

우선, State를 사용하려면 리액트의 기능 중 useState를 import 해야한다. useState는 배열을 반환하여 비구조화 할당을 이용해 0번째 인덱스를 count에 저장하고, 1번째 인덱스는 setCount에 할당해준다. count는 상태 값을 나타내고 setCount는 그 count 값을 변화시키는 상태 변화 함수이다. useState 메소드에 넘겨준 인자 0은 count라는 상태의 초기값을 설정해준 것이다.

버튼을 눌렀을 때 숫자를 증가시키거나 감소시키기 위해, onClick 이벤트를 사용해준다. 

javascript에서는 onClick 함수를 onclick="함수명()" 형식으로 사용하고,

React에서는 onClick 함수를 onclick={함수명} 형식으로 사용한다.

 

->컴포넌트는 자신이 가진 state가 변화하면 화면을 다시 그려 re-render를 한다. 즉, 함수가 다시 호출된다.


◈ Props란?

: 상위(부모 컴포넌트)에서 하위(자식 컴포넌트)로 데이터(값)을 전달할 때 사용.

 

App.js에서 Counter.js로 0 대신에 초기값을 전달해주고 싶다. 이럴 때 props를 사용하는 것이다.

App.js

const App = () => {
  return (
    <div>
      <Counter initialValue={5}/>
    </div>
  );
}

Counter.js

import React,{useState} from "react";

const Counter=(props)=>{
    console.log(props);

    const [count,setCount] = useState(props.initialValue)

    const onIncrease = () => {
        setCount(count+1);
    };
    const onDecrease = () => {
        setCount(count-1);
    };
    return(
        <div>
            <h2>{count}</h2> 
            <button  onClick={onIncrease}>+</button>
            <button onClick={onDecrease}>-</button>
        </div>
    );
};

export default Counter;

Counter.js에서 매개변수로 props를 받았다. 

 

여러 개의 props를 보내고 싶을 때는 어떻게 할까? 이럴 때는 객체 안에 담아서 보내면 깔끔하게 코드를 짤 수 있다.

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

const App = () => {
  const counterProps ={
    a : 1,
    b : 2,
    c : 3,
    d : 4,
    initialValue : 5
  }
  return (
    <div>
      <Counter {...counterProps}/>
    </div>
  );
}

전달해야 할 props들을 객체로 만들어서 객체를 펼쳐서 전달하는 스프레드 연산자 {...이름}을 통해 전달하는 방식이다.

import React,{useState} from "react";

const Counter=({initialValue})=>{
    console.log(props);

    const [count,setCount] = useState(initialValue)

    const onIncrease = () => {
        setCount(count+1);
    };
    const onDecrease = () => {
        setCount(count-1);
    };
    return(
        <div>
            <h2>{count}</h2> 
            <button  onClick={onIncrease}>+</button>
            <button onClick={onDecrease}>-</button>
        </div>
    );
};

Counter.defaultProps={
	initialValue:0,
};

export default Counter;

이 경우에는 props로 전달 받은 값들 중에서 initialValue만 꺼내 쓴 경우이다. Counter.defaultProps는 만약 부모 컴포넌트에서 원하는 props의 내용이 오지 않았을 경우에 대비해 default 값을 설정해준 것이다. (에러 방지)

 

◈ Props가 전달하는 데이터

: props는 자식 컴포넌트에게 정적인 데이터 뿐만 아니라 동적인 데이터도 전달할 수 있다.

//OddEvenResult.js

const OddEvenResult = ({count}) => {
    return <>{count%2===0? "짝수" : "홀수"}</>    
};

export default OddEvenResult;


//Counter.js
import React,{useState} from "react";
import OddEvenResult from "./OddEvenResult";

const Counter=(props)=>{
    const [count,setCount] = useState(props.initialValue)

    const onIncrease = () => {
        setCount(count+1);
    };
    const onDecrease = () => {
        setCount(count-1);
    };
    return(
        <div>
            <h2>{count}</h2> 
            <button  onClick={onIncrease}>+</button>
            <button onClick={onDecrease}>-</button>
            <OddEvenResult count={count}/>
        </div>
    );
};

export default Counter;

useState의 비구조화 할당을 통해 만들어진 0번째 인덱스 count를 props로 전달한 것이다. 결과를 보면 count의 state가 바뀔 때마다 짝수/홀수가 계속 바뀌며 화면에 출력된다. 이는 부모가 전달하는 props가 변경되면 리랜더링 하는 것이다. 

 

심지어 자식 컴포넌트가 props를 받지 않고, 혼자 랜더링을 한다고 해도 부모 요소가 변경되면(Counter 컴포넌트의 state가 변경될 때) 자식 컴포넌트 (OddEvenResult) 도 계속해서 리랜더링 된다.

 

props로 컴포넌트 자체도 다른 컴포넌트의 props로 전달할 수 있다.

//Container.js

const Container=({children})=>{
    return (
        <div style={{margin: 20, padding: 20, border: "1px solid gray"}}>
            {children}
        </div>
    );
};

export default Container;

//App.js
import React from "react";
import Container from "./container";
import Counter from "./counter";


const App = () => {
  return (
    <Container>
      <div>
        <Counter/>
      </div>
    </Container>
  );
}

export default App;

<Counter>컴포넌트 안에 JSX요소(html)를 자식으로 배치하게 되면 Container 컴포넌트에 prop으로 전달이 된다.

 

◈ 랜더링을 실행하는 경우

1. 리액트의 컴포넌트는 본인이 관리하고 본인이 가지는 state가 바뀔 때

2. 나에게 내려오는 props가 바뀔 때

3. 내 부모 컴포넌트가 랜더링 될 때

Comments