안녕하세요, 코린이의 코딩 학습기 채니 입니다.
[리액트를 다루는 기술]의 책을 참고하여 포스팅한 개인 공부 내용입니다.
state
- 컴포넌트 내부에서 바뀔 수 있는 값
props는 컴포넌트가 사용되는 과정에서 부모 컴포넌트가 설정하는 값으로, 컴포넌트 자신은 해당 props를 읽기 전용으로만 사용할 수 있습니다.
즉, props를 변경하려면 부모 컴포넌트에서 바꿔줘야 하는 것이죠.
그에 반면 state는 컴포넌트 내부에서 값을 변경할 수 있습니다.
클래스형 컴포넌트의 state
Counter.js
import { Component } from "react";
class Counter extends Component {
constructor(props) {
super(props);
// state 초깃값 설정
this.state = {
number : 0
};
}
render() {
const {number} = this.state; // state 조회
return (
<div>
<h1>{number}</h1>
<button
// onClick을 통해 버튼이 클릭되었을 때 호출할 함수 지정
onClick={() => {
// this.setState로 state에 새로운 값 넣음
this.setState({number : number + 1});
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
App.js
import './App.css'
import Counter from './Counter';
const App = () => {
return <Counter />;
}
export default App;
버튼을 누를 때마다 숫자가 증가하는 것을 확인할 수 있습니다.
* 코드 파악하기
constructor(props) {
super(props);
// state 초깃값 설정
this.state = {
number : 0
};
}
컴포넌트에 state를 설정할 때 constructor 메소드를 작성하여 설정합니다.
클래스형 컴포넌트에서 constructor를 작성할 때는 반드시 super(props)를 호출해야 합니다.
호출 시 상속 받고 있는 리액트의 Component 클래스가 지닌 생성자 함수를 호출 해줍니다.
this.state로 초깃값을 설정해주었으며, 객체 형식이여야 합니다.
render() {
const {number} = this.state; // state 조회
return (
<div>
<h1>{number}</h1>
<button
// onClick을 통해 버튼이 클릭되었을 때 호출할 함수 지정
onClick={() => {
// this.setState로 state에 새로운 값 넣음
this.setState({number : number + 1});
}}
>
+1
</button>
</div>
);
}
현재 state를 조회하고 싶다면, this.state를 조회해줍니다.
onClick으로 버튼 클릭 시 호출할 함수를 지정해주었고, this.setState 함수를 통해 state 값을 변경 시켜주었습니다.
(이벤트로 설정할 함수를 넣어줄 때는 화살표 함수 문법 사용)
state 객체 안에 여러 값이 있을 때
Counter.js
import { Component } from "react";
class Counter extends Component {
constructor(props) {
super(props);
// state 초깃값 설정
this.state = {
number : 0,
fixedNumber : 0
};
}
render() {
const {number, fixedNumber} = this.state; // state 조회
return (
<div>
<h1>{number}</h1>
<h2>바뀌지 않는 값 : {fixedNumber}</h2>
<button
// onClick을 통해 버튼이 클릭되었을 때 호출할 함수 지정
onClick={() => {
// this.setState로 state에 새로운 값 넣음
this.setState({number : number + 1});
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
fixedNumber를 추가해주었고, 버튼 클릭 시 fixedNumber는 그대로 유지 / number는 +1 처리 해주었습니다.
fixedNumber는 그대로 0인 것을 확인할 수 있습니다.
this.setState 함수는 인자로 전달된 객체 안에 들어 있는 값만 변경해준다는 것을 알 수 있습니다.
state를 constructor에서 꺼내기
Counter.js
import { Component } from "react";
class Counter extends Component {
state = {
number : 0,
fixedNumber : 0
}
render() {
const {number, fixedNumber} = this.state; // state 조회
return (
<div>
<h1>{number}</h1>
<h2>바뀌지 않는 값 : {fixedNumber}</h2>
<button
// onClick을 통해 버튼이 클릭되었을 때 호출할 함수 지정
onClick={() => {
// this.setState로 state에 새로운 값 넣음
this.setState({number : number + 1});
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
state 초깃값을 constructor에서 지정해주었는데, 이를 선언하지 않고도 state 초깃값을 설정해주었습니다.
훨씬 간편하죠!
this.setState에 객체 대신 함수 인자 전달하기
Counter.js - button onClick
onClick={() => {
// this.setState로 state에 새로운 값 넣음
this.setState({number : number + 1});
this.setState({number : this.state.number + 1});
}}
this.setState를 두 번 사용했지만 버튼을 클릭하면 1씩 증가됩니다.
그 이유는 this.setState를 사용한다고 해서 state 값을 바로 변경되지는 않기 때문인데요!
바로바로 값이 반영되고자 한다면 (2씩 증가), 객체 대신 함수를 인자로 넣어줍니다.
Counter.js - button onClick
<button
// onClick을 통해 버튼이 클릭되었을 때 호출할 함수 지정
onClick={() => {
// this.setState로 state에 새로운 값 넣음
this.setState((prevState, props) => {
return {
// 업데이트 하고 싶은 내용
number : prevState.number + 1
};
});
// 위 코드와 아래 코드는 동일한 역할 수행
// 아래 코드는 함수에서 바로 객체를 반환
this.setState(prevState => ({
number : prevState.number + 1
}));
}}
>
+1
</button>
버튼을 클릭할 때마다 2씩 증가하는 것을 확인할 수 있습니다.
prevState는 기존 상태이고, props는 현재 지니고 있는 props를 가리킵니다.
this.setState가 끝난 후 특정 작업 실행하기
setState의 두 번째 파라미터로 콜백 함수를 등록하여 작업을 처리할 수 있습니다.
Counter.js - button onClick
<button
// onClick을 통해 버튼이 클릭되었을 때 호출할 함수 지정
onClick={() => {
this.setState(
{number : number + 1},
// 콜백함수
() => {
console.log('방금 setState가 호출되었습니다.');
console.log(this.state);
}
)
}}
>
+1
</button>
후처리가 잘 되는 것을 확인할 수 있습니다.
함수 컴포넌트에서 useState 사용하기
useState 사용하기
Say.js
import { 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는 객체가 아니어도 상관 없습니다.
useState 함수를 호출하게 되면 배열이 반환되고,
첫 번째 원소는 현재 상태 / 두 번째 원소는 상태를 바꾸어주는 함수 (setter) 입니다.
따라서 setter 함수에 의해 message가 변경되는 것이죠.
App.js
import Say from './Say';
const App = () => {
return <Say />;
}
export default App;
한 컴포넌트에서 useState 여러 번 사용하기
Say.js
import { 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')}>빨간색</button>
<button style={{color : 'green'}} onClick={() => setColor('green')}>초록색</button>
<button style={{color : 'blue'}} onClick={() => setColor('blue')}>파란색</button>
</div>
);
};
export default Say;
state 사용 시 주의 사항
- state 값을 바꾸어야 할 때는 setState 혹은 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: 2}; // 사본을 만들어서 b 값만 덮어쓰기
// 배열 다루기
const array = [
{ id: 1, value: true },
{ id: 2, value: true },
{ id: 3, value: false }
];
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인
'JavaScript > React' 카테고리의 다른 글
React) ref - DOM에 이름 달기, state를 이용해 기능 구현 (0) | 2022.11.11 |
---|---|
React) 이벤트 핸들링 (클래스형 컴포넌트, 함수형 컴포넌트) (0) | 2022.11.10 |
React) props에 대해서 (0) | 2022.11.01 |
React) 컴포넌트의 종류, 컴포넌트 생성해보기 (0) | 2022.11.01 |
React) JSX 문법에 대하여 (0) | 2022.10.27 |