본문 바로가기
한 입 크기로 잘라먹는 React

4. React.js 의 State와 Props

by bammbii 2024. 5. 31.

[ State로 상태 관리하기]

하나의 컴포넌트에 여러 개의 state를 만들 수 있음

리렌더링 (Re-Rendering) :  컴포넌트의 state 값이 바뀌면 그 컴포넌트가 return 을 다시 해서 화면을 다시 그림

이 때, 변경된 state 값도 함께 반영

 

1. 새로운 state를 생성하는 useState라는 함수는 인수로 초깃값을 받아서 두 개의 요소를 담은 배열을 반환하는데 첫 번째 요소는 state의 현재 값이고 두 번째 요소는 state를 변경시키는 상태변화함수이다. 

2. useState() 생성 시 괄호 안에 값을 넣어 state 값을 생성할 수 있다.

 

 

그런데 그냥 변수 하나 만들어서 관리하면 그게 state랑 똑같은 거 아님?

=> 그렇게 하면 버튼이 클릭될때마다 변수의 값이 바뀔 순 있음 

그렇지만, 변수의 값이 바뀐다고 컴포넌트 리렌더링 되진 않음

그래서 아무리 버튼을 클릭해도 아무 변화도 일어나지 않음 

 

[ State와 Props]

1. 25번째 줄의 light state가 바뀌게 되면 Blob 컴포넌트도 리렌더링 됨 

=> 리액트 컴포넌트들은 자신이 갖는 state가 변경되지 않아도

부모로부터 받는 props의 값이 바뀌게 되면 리렌더링이 발생

 

< 리액트 컴포넌트가 리렌더링되는 상황 >

1. 자신이 관리하는 state의 값이 변경될 때

2. 자신이 제공받는 props의 값이 변경될 때

3. 부모 컴포넌트가 리렌더링 되면 자식 컴포넌트도 리렌더링 

 

+버튼을 누르면 count state가 변경되면서 App 컴포넌트가 가진 state가 변경되므로 리렌더링이 일어남 (1번)

→ App의 자식 컴포넌트인 Blub 컴포넌트의 리렌더링이 일어남 (3번)

 +버튼을 누를 때(count state가 변경될 때)마다 전혀 상관없는 Blub 컴포넌트의 리렌더링이 일어남

 이걸 방지하기 위해 관련이 없는 두 개의 state를 서로 다른 컴포넌트로 분리함 (사진)

 

이렇게 되면 App 컴포넌트에 count, light state가 같이 존재하는게 아니라

Counter 컴포넌트에 count state, Blub 컴포넌트에 light state가 존재하기 때문에

각각의 state가 변화하더라도 각 컴포넌트만 리렌더링하게 됨

 

[ State로 사용자 입력 관리하기 ]

< 간단한 회원가입 폼 만들기 >

이제 중복되는 코드를 제거해보자.

'name, birth, country, bio' 각각의 state를 관리하는 것보다 하나의 객체로 만들고

하나의 state로 만들어서 관리하도록 구현.

import { useState } from "react";

//간단한 회원가입 폼
const Register = () => {
    const[input, setInput] = useState({
        name : "",
        birth: "",
        country: "",
        bio: "",
    });

    const onChangeName = (e) => {
        setInput({
            // 관련 없는 값들은 그대로 유지
            ...input, 
            name: e.target.value
        })
    };

    const onChangeBirth = (e) => {
        setInput({
            ...input, 
            birth: e.target.value
        })
    };

    const onChangeCountry = (e) => {
        setInput({
            ...input, 
            country: e.target.value
        })    
    }

    const onChangeBio = (e) => {
        setInput({
            ...input, 
            bio: e.target.value
        }) 
    }

    return (
        <div>
            <div>
                <input value={input.name} onChange={onChangeName} placeholder={"이름"}></input>
            </div>
            <div>
                <input value={input.birth} onChange={onChangeBirth} type="date"></input>
            </div>
            <div>
                <select value={input.country} onChange={onChangeCountry}>
                    <option></option>
                    <option value="kr">한국</option>
                    <option value="us">미국</option>
                    <option value="uk">영국</option>
                </select>
                {input.country}
            </div>
            <div>
                <textarea value={input.bio} onChange={onChangeBio}></textarea>
            </div>
        </div>
    );
};
export default Register;

 

 

그리고 상태를 변경할 때 

Spread 연산자를 통해 변경하지 않는 값들은 그대로 유지시키고 변경할 값만 넣어주었는데,

여전히 반복되는 코드들이 존재함 (onChange~의 반복)

 

 

import { useState } from "react";

//간단한 회원가입 폼
const Register = () => {
    const[input, setInput] = useState({
        name : "",
        birth: "",
        country: "",
        bio: "",
    });

    // 통합이벤트핸들러  
    const onChange = (e) => {
        setInput({
            ...input,
            [e.target.name] : e.target.value,
        })
    }

    return (
        <div>
            <div>
                <input name="name" value={input.name} onChange={onChange} placeholder={"이름"}></input>
            </div>
            <div>
                <input name="birth" value={input.birth} onChange={onChange} type="date"></input>
            </div>
            <div>
                <select name="country" value={input.country} onChange={onChange}>
                    <option></option>
                    <option value="kr">한국</option>
                    <option value="us">미국</option>
                    <option value="uk">영국</option>
                </select>
                {input.country}
            </div>
            <div>
                <textarea name="bio" value={input.bio} onChange={onChange}></textarea>
            </div>
        </div>
    );
};
export default Register;

 

그래서 onChange라는 이벤트 핸들러를 만들고 객체를 만들어서 전달할 때

name 자리에 점표기법을 이용하여 변수로 넣을 수 있도록 함.

 

결과적으로 코드의 양이 훨씬 줄어든 것을 확인할 수 있음.

'한 입 크기로 잘라먹는 React' 카테고리의 다른 글

7. 실습 : 카운터 앱 만들기  (0) 2024.06.01
5. React.js의 useRef  (0) 2024.05.31
3. React.js 입문  (0) 2024.05.30
2. React.js  (0) 2024.05.30
1. Node.js 기초  (0) 2024.05.30