컴포넌트 내부에서 바뀔 수 있는 값을 의미한다.
props는 컴포넌트가 사용되는 과정에서 부모 컴포넌트가 설정하는 값이고, 컴포넌트 자신은 props를 읽기 전용으로 사용할 수 있다.
컴포넌트에 state를 설정할 때는 constructor 메서드를 작성하여 설정한다.
컴포넌트의 state는 객체 형식이어야 한다.
constructor(props) {
super(props);
this.state = {
number: 0,
};
}
constructor: 컴포넌트의 생성자 메서드
render() {
const { number } = this.state;
return (
<div>
<h1>{number}</h1>
<button
onClick={() => {
this.setState({ number: number + 1 });
}}
>
+1
</button>
</div>
);
}
button의 onClick은 button이 클릭될 때 호출시킬 함수를 설정한다. (이벤트를 설정한다고 말한다.) 이벤트로 설정할 함수를 넣어줄 때는 화살표 함수 문법을 사용하여 넣어주어야 한다.
this.setState 함수를 통해서 state 값을 바꿀 수 있게 한다.
state = {
number: 0,
fixedNumber: 0,
};
setState를 호출한 직후에 this.state에 접근하는 것은 좋지 않다. 이전 상태를 기반하여 상태를 변경해야 한다면 updater 함수를 사용하는 것이다.
updater 함수를 setState 메소드의 첫번째 인자로 넘기는 방식으로 사용할 수 있다.
onClick={() => {
this.setState((prevState) => {
return {
number: prevState.number + 1,
};
});
}}
updater의 인자(prevState)는 최신상태를 기반으로 하기 때문에 두번을 호출하면 2가 더해진다. 하지만 this.setState({ number: number + 1 });을 두번 호출하게 되면 리액트는 이것을 하나로 합쳐서 변경하기 때문에 1만 증가된다.
this.setState(
(prevState) => ({
number: prevState.number + 1,
}),
() => {
console.log("방금 setState가 호출되었습니다.");
}
);
this.setState()는 파라미터가 updater와 callback 함수로 되어 있다.
(prevState) => ({
number: prevState.number + 1,
})
() => {
console.log("방금 setState가 호출되었습니다.");
}
리액트 16.8 이후 버전에서 사용 가능한 함수이다. Hooks 개념이 필요하다.
객체 비구조화 할당과 비슷한 모습을 가진다.
const array = [1, 2];
const one = array[0];
const two = array[1];
const [one, two] = array;
array 안에 있는 값을 one, two에 할당하는 코드, 배열의 비구조화 할당을 통해서 표현할 수 있다.
useState 함수를 호출하면 배열이 반환된다.
배열의 첫 번째 원소 : 현재 상태 (message)
배열의 두 번째 원소 : 상태를 바꾸어주는 함수 (세터(Setter) 함수) (setMessage)
배열의 원소 이름은 자유롭게 정해주어도 상관없다.
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 함수의 인자에는 상태의 초깃값을 넣어준다.useState(['??', ''])라고 초깃값을 넣어주게 되면 화면 처음 message의 값은 '??'이 된다.
클래스형 컴포넌트에서 state의 초깃값은 객체 형태를 넣어주어야 하지만, useState의 초깃값은 반드시 객체가 아니여도 상관 없다.
배열의 첫 번째 원소는 현재 상태, 두 번째 원소는 상태를 바꾸어주는 함수
세터(Setter) 함수 : 상태를 바꾸어주는 함수
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")}>
빨간색
</button>
<button style={{ color: "green" }} onClick={() => setColor("green")}>
초록색
</button>
</div>
);
state 값을 바꿀 때는 반드시 setState or useState를 통해 전달받은 세터 함수를 사용하자.
this.state.number = this.state.number + 1;
this.state.array = this.array.push(2);
this.state.object.value = 5;
const [object, setobject] = useState({ a: 1, b: 1 });
object.b = 2;
기존의 배열이나 객체 사본을 만들고 사본에 값을 업데이트한다.
그 사본의 상태를 setState 혹은 세터함수를 통해 업데이트 한다.
const object = { a: 1, b: 2, c: 3 };
const nextObject = { ...object, b: 4 };
const array = [
{ id: 1, value: true },
{ id: 2, value: true },
{ id: 3, value: true },
];
let nextArray = array.concat({ id: 4 });
nextArray.filter((item) => item.id !== 2); //id가 2인 항목 제거
nextArray.map((item) => (item.id === 1 ? { ...item, value: false } : item)); //id가 1인 항목의 value를 false로 설정
객체에 대한 사본을 만들 때는 spread 연산자(...)를 사용해서 처리한다.
배열에 대한 사본을 만들 때는 배열의 내장함수들을 활용한다.