리액트 Props & State Q&A 정리

라용·2022년 9월 4일
0

위코드 파운데이션 과정을 들으며 정리한 내용입니다.

Props & State

props 는 컴포넌트의 속성 값입니다. 부모 컴포넌트에게 props 형태로 속성값을 주면 자식 컴포넌트에게 객체 형태의 데이터를 전달합니다. state 는 변하는 값을 저장합니다. 값이 변할 때 단순히 재할당만 하는 것이 아니라 실제 UI를 바뀐 값으로 렌더링 해줍니다. (변수 재할당은 화면에 다시 그려지지 않음)

컴포넌트의 분리

컴포넌트을 어떻게 얼마나 분리하라는 정해진 규칙은 없습니다. 보통 페이지에서 유의미한 구획들 기준으로 (화면 U) 나누고, 코드를 보았을 때 컴포넌트 구성을 파악하가 쉽게 만드는 게 좋습니다. 다른 UI 에 재사용해야 하는 요소라면 컴포넌트로 만듭니다. 처음이라면 일단 잘게 쪼개보고, 불편하면 다시 합쳐보면서 어떤 식의 분리가 좋을지 고민해보면 좋습니다.

데이터 할당

기본형 데이터(number, string, boolean...)는 변수를 선언하고 할당할 때 해당 값 자체를 메모리에 저장하지만, 참조형 데이터(객체, 배열..)는 객체 안의 값은 다른 곳에 저장하고 그 틀만 메모리에 저장합니다. 그래서 객체안의 값이 바뀌어도 객체 자체는 바뀌지 않습니다. (내부의 값이 바뀌는 배열이나 객체를 const 로 선언해도 괜찮은 이유) 같은 이유로 객체나 배열 안의 값이 바뀌어도 변수가 그 주소값을 바라보고 있다는 것은 그대로라서 화면이 재 렌더링 되지 않습니다. 그래서 State 사용하거나 전개구문으로 복제해서 사용하기도 합니다.

const obj = {
	name : "라용";
}

const copyObj = { ... obj }; //=> { name : "라용" }
// 기존 객체를 풀었다가 다시 객체로 묶어준 것

동기적, 비동기적 초리

동기는 코드를 순차적으로 실행하고 비동기는 특정 코드가 끝나는 것을 기다리지 않고 다른 것을 실행합니다. State 를 업데이트 할 때 바로 랜더링 되는 것은 비동기적 처리입니다.

import React, { useState } from "react";

function Child() {
	const [num, setNum] = useState(0);
	
	const handleClick = () => {
		setNum(num + 1);
	}
	
	return (
		<>
			<p>{ num }</p>
			<button onClick={handleClick}>+1</button>
		</>
	);
}

export default Child;

위 코드는 버튼을 누를 때마다 비동기적으로 숫자 1을 더해줍니다. 대신 아래와 같이 작성할 경우 순차적으로 더해주지 않아 한번의 클릭에 1만 더해주게 됩니다.

import React, { useState } from "react";

function Child() {
	const [num, setNum] = useState(0);
	
	const handleClick = () => {
		setNum(num + 1);
		setNum(num + 1);
		setNum(num + 1);
	}
	
	return (
		<>
			<p>{ num }</p>
			<button onClick={handleClick}>+1</button>
		</>
	);
}

export default Child;

1씩 더해주고 싶다면 아래처럼 함수형으로 업데이트 해야 합니다.

import React, { useState } from "react";

function Child() {
	const [num, setNum] = useState(0);
	
	const handleClick = () => {
		setNum((prev) => prev + 1);
		setNum((prev) => prev + 1);
		setNum((prev) => prev + 1);
	};
	
	return (
		<>
			<p>{ num }</p>
			<button onClick={handleClick}>+1</button>
		</>
	);
}

export default Child;

구조분해할당

props 로 데이터를 가져올 때 아래처럼 구조분해할당을 사용할 수 있습니다.

function Chlid(props) {
	const name = props.name;
	const age = props.age;
	const isMale = props.isMale;
	
	// 위 3줄을 구조분해할당으로 적으면 
	
	const { name, age, isMale } = props;

state 선언도 자세히 보면 배열의 구조분해 할당입니다. const [state, setState] = useState();
자식 요소가 Props로 데이터를 받을 때 구조분해할당을 하면 더 간단합니다.

function Chlid({ name, age, isMale }) { .. }

예시 코드

버튼을 눌렀을 때 타이틀의 색상이 바뀌는 코드를 짠다고 한다면, 일단 기본 틀은 아래와 같고

// Main.js
import React from "react";
import Title from "./Title";
import Button from "./Button"

function Main() {
	return (
		<Title />
		<Button />
	);
}

export default Main;
//Title.js
import React from "react"

function Title() {
	return <h1> 제목을 쓰세요 </h1>
}

export default Title;
//Button.js
import React from "react";

function Button() {
	return <button>색 변경 버튼</button>;
}

export default Button;

부모 컴포넌트인 Main 에서 State 를 선언하고 setState() 바꾸어준 값을 자식 컴포넌트인 Title 과 Button 에 Props 형태로 전달합니다.

// Main.js
import React from "react";
import Title from "./Title";
import Button from "./Button"

function Main() {
	const [isCllicked, setIsClicked] = useState(true);
	
	const toggleBtnColor = () => {
		if (isClicked === true) {
			setIsClicked(false);
		} else {
			setIsClicked(true);
		}
	}
	
	return (
		<Title isClicked={isClicked}/>
		<Button toggleBtnColor={toggleBtnColor}/>
	);
}

export default Main;
//Title.js
import React from "react"

function Title({ isClicked }) {
	return <h1 style={{ color: isClicked ? "red" : "blue" }}> 제목을 쓰세요 </h1>
}

export default Title;
//Button.js
import React from "react";

function Button({ toggleBtnColor }) {
	return <button onClick={toggleBtnColor}>색 변경 버튼</button>;
}

export default Button;

부모컴포넌트의 조건문을 축약하고 설명을 조금 더 해보면,

// Main.js
import React from "react";
import Title from "./Title";
import Button from "./Button"

function Main() {
	const [isCllicked, setIsClicked] = useState(true);
	
	const toggleBtnColor = () => {
		setIsClicked(!isClicked);
	}
	
	return (
		<Title isClicked={isClicked}/>  // 변화하는 State 상태값 전달
		<Button toggleBtnColor={toggleBtnColor}/> // State 를 변경하는 함수 전달
	);
}

export default Main;
//Title.js
import React from "react"

function Title({ isClicked }) { // Props 데이터를 구조분해할당으로 받기
	return <h1 style={{ color: isClicked ? "red" : "blue" }}> 제목을 쓰세요 </h1>
	// 인라인으로 스타일 속성을 주는 것이라 {} 를 한번 더 감싼다.
}

export default Title;
//Button.js
import React from "react";

function Button({ toggleBtnColor }) { // Props 데이터를 구조분해할당으로 받기
	return <button onClick={toggleBtnColor}>색 변경 버튼</button>;
	// onClick 이벤트에 함수 동작하기
}

export default Button;
profile
Today I Learned

0개의 댓글