728x90
state 란?
- 컴포넌트 내부에서 바뀔 수 있는 값을 의미한다
- 클래스형 컴포넌트가 지니고 있는 state와 함수 컴포넌트에서 useState라는 함수를 통해 사용하는 state가 있다
- 컴포넌트 자체적으로 지닌 값으로 컴포넌트 내부에서 값을 업데이트할 수 있다
클래스형 컴포넌트 state ( state 초기값 설정 방법 1)
- 컴포넌트에 state의 초기값을 설정할 때는 constructor 메서드(컴포넌트 생성자 메서드)를 작성하여 설정한다
- 클래스형 컴포넌트에서 constructor를 작성할 때는 반드시 super(props)를 호출해주어야 한다. (이 함수가 호출되면 현재 클래스형 컴포넌트가 상속받고 있는 리액트의 Component 클래스가 지닌 생성자 함수를 호출해준다)
- 컴포넌트의 state는 객체 형식 이어야 한다.
// 자식 컴포넌트
import {Component} from 'react';
class Counter extends Component {
// state 초기값 설정 하기 위해 constructor 메소드 작성
constructor(props){
super(props);
this.state = { // this.state 의 값에 초기값을 설정 해주었다
number : 0 // 초기값 설정
};
}
render() {
const { number } = this.state; // state 를 조회 할때는 this.state로 조회 한다
return (
<div>
<h1>{number}</h1>
<button
/*
onclick 을 통해 버튼이 클릭되었을때 호출할 함수를 지정.
이벤트로 설정할 함수를 넣어줄때는 화살표 함수 문법을 사용해서 넣어주어야한다
*/
onClick={() => {
// this.setState 를 사용해서 state에 새로운 값을 넣을 수 있다
this.setState({ number: number + 1 });
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
// 부모 컴포넌트
import Counter from './Counter';
const App = () => {
return <Counter/>;
};
export default App;
state ( state 초기값 설정 방법 2)
- constructor 메서드를 선언하지 않고도 state를 사용해서 state 초기값을 설정할 수 있다
// 자식 컴포넌트
import {Component} from 'react';
class Counter extends Component {
// constructor 메소드를 선언 하지 않고도 state 를 사용해서 state의 초기값을 설정할 수 있다
state = {
// 초기값 설정
number : 0,
fixedNumber: 0
};
render() {
const { number,fixedNumber} = this.state; // state 를 조회 할때는 this.state로 조회 한다
return (
// 생략...
);
}
}
export default Counter;
state 객체 안에 여러 값이 있을 때
- state 객체 안에 여러 값이 있어도 인자로 전달되는 객체 내부에 전달되지 않으면 값이 바뀌지 않는다
- this.setState 함수는 인자로 전달된 객체 안에 들어 있는 값만 바꾸어준다
// 자식 컴포넌트
import {Component} from 'react';
class Counter extends Component {
// state 초기값 설정 하기 위해 constructor 메소드 작성
constructor(props){
super(props);
this.state = {
// 초기값 설정
number : 0,
fixedNumber: 0
};
}
render() {
const { number ,fixedNumber } = this.state; // state 를 조회 할때는 this.state로 조회 한다
return (
<div>
<h1>{number}</h1>
<h2>{fixedNumber}</h2>
<button
onClick={() => {
// this.setState 함수는 인자로 전달된 객체 안에 들어 있는값만 바꾸어준다
this.setState({ number: number + 1 });
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
this.setState
- this.setState를 사용하면 state에 새로운 값을 넣을 수 있다
- this.setState를 사용해서 state 값을 업데이트할 때는 상태가 비동기적으로 업데이트된다
/*
this.setState를 사용해서 state 값을 업데이트 하면 비동기적으로 업데이트 되기 때문에 이렇게 두번 호출 할 경우
분명 2번 사용하는 것이기 때문에 숫자가 2개씩 더해질거라 생각 했는데 버튼을 클릭할때 숫자가 1씩 더해지게 된다
그 이유는, this.setState를 사용한다고 해서 state 값이 바로 바뀌지 않기 때문이다
이 방법의 해결 책은 this.setState를 사용할때 객체 대신에 함수를 인자로 넣는것 이다.
*/
onClick = {() => {
this.setState({ number: number + 1 });
this.setState({ number: this.state.number + 1});
}}
// 함수를 인자로 넣어주는 코드
onClick = {() => {
/*
prevState 는 기존 상태이고 props는 현재 지니고 있는 props 를 가리킨다 만약 업데이트 하는 과정에서
props 가 필요없으면 생략 해도 된다
*/
this.setState((prevState, props) => {
return {
// 업데이트하고 싶은 내용
}
});
}}
// 함수를 인자로 넣어주는 코드 props 생략
onClick = {() => {
this.setState((prevState => {
return {
// 업데이트하고 싶은 내용
number :prevState.number +1
}
});
}}
/*
위 코드랑 완전 똑같지만 이 코드는 함수에서 바로 객체를 반환 한다는 의미의 함수이다
화살표 함수에서 값을 바로 반환하고 싶을때는 코드 블록 {} 를 생략한다
그래서 prevState => ({}) 형태의 코드
*/
onClick = {() => {
this.setState(prevState => ({
return {
// 업데이트하고 싶은 내용
number :prevState.number +1
}));
}}
this.setState를 사용해 값을 업데이트한 후 특정 작업을 하고 싶을 때
- setState를 사용해 값을 업데이트한 후 특정 작업을 하고 싶을 때는 setState 두 번째 파라미터로 콜백 함수를 등록하면 된다
onclick = {() => {
this.setState(
{
number: number + 1
},
// 두번째 파라미터로 콜백함수 등록
() = > {
console.log(this.state); // {number:1}
}
);
}}
함수 컴포넌트 useState
- 리액트 16.8 이후부터는 useState라는 함수를 사용해서 함수 컴포넌트에서도 state를 사용할 수 있게 되었다 (이 과정에서 Hooks을 사용하게 된다)
- useState 함수의 인자에는 상태의 초기값을 넣어주는데 이때 값의 형태는 state과 다르게 반드시 객체가 아니어도 된다 (숫자, 문자, 객체, 배열.. 다 가능 )
- 함수를 호출하면 배열이 반환되는데 배열의 첫 번째 원소는 현재 상태이고 두 번째 원소는 상태를 바꾸어주는 함수이다 ( 이를 세터(Setter) 함수라고 한다)
- 배열 비구조화 할당을 통해 이름은 자유롭게 정할 수 있다
- useState는 한 컴포넌트에서 여러 번 사용해도 상관없다
- 새로운 컴포넌트를 만들 때 클래스형 컴포넌트 state 보다 useState 사용을 더 권장한다 (코드가 더 간결해진다)
// 자식 컴포넌트
import { useState } from 'react';
const Say = () => {
/*
배열 비구조화 할당을 통한 message(현재상태), setMessage(상태를 바꾸어주는함수) 이름 설정은
자유롭게 해도 된다. 예) text setText 로 해도 상관없음
*/
const[message, setMessage] = useState('');
const onClickEnter = () => setMessage('hi');
const onClickLeave = () => setMessage('bye');
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>
);
};
export default Say;
// 부모 컴포넌트
import Say from './Say';
const App = () => {
return <Say />;
};
export default App;
state를 사용할 때 주의 사항
- state 값을 바꾸어야 할 때는 setState 혹은 useState를 통해 전달받은 세터(Setter) 함수를 사용해야 한다
- 배열이나 객체를 업데이트해야 할 때는 배열이나 객체 사본을 만들고 그 사본에 값을 업데이트한 후 , 그 사본의 상태를 setState 혹은 세터(Setter) 함수를 통해 업데이트해주어야 한다
/* 잘못된 코드 */
// 클래스형 컴포넌트 에서 ..
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;
// 제대로 된 코드
/*
객체 다루기
객체에 대한 사본을 만들때는 spread 연산자라 불리는 ... 을 사용해서 처리한다
*/
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인 항목 제거
// id 가 1인 항목의 value 를 false로 설정
nextArray.map(item = > item.id === 1 ? { ...item, value : false } : item));
728x90
'React > 기초' 카테고리의 다른 글
리액트[기초] 라이프사이클 메서드 (0) | 2022.05.29 |
---|---|
리액트[기초] Hook 훅 (0) | 2022.05.28 |
리액트[기초] propTypes (0) | 2022.05.27 |
리액트[기초] 비구조화 할당 문법(구조 분해 문법) | 배열 비구조화 할당 (0) | 2022.05.27 |
리액트[기초] props.children (0) | 2022.05.27 |