🚀
리액트에서 setState 후 변경된 state값을 사용하는 경우가 종종 있으며, Callback 함수를 사용하여 해결할 수 있습니다.
🚩 setState를 한 뒤 state를 사용하는 경우
📋 코드
import React, { Component } from "react";
import styled from "styled-components";
import "./App.css";
const Wrapper = styled.div`
display: flex;
margin: 20px;
`;
const Print = styled.div`
border-radius: 5px;
border: 1px solid #6c757d;
width: 80px;
height: 30px;
font-size: 20px;
text-align: center;
`;
const Button = styled.button`
background-color: #6c757d;
border-radius: 5px;
border: 0px;
color: white;
width: 80px;
height: 30px;
margin-left: 10px;
&:hover {
background-color: #5a6268;
}
`;
class App extends Component {
constructor(props) {
super(props);
this.state = { counter: 0 };
}
onClick = () => {
this.setState({ counter: this.state.counter + 1 });
console.log(this.state.counter);
};
render() {
return (
<Wrapper>
<Print>{this.state.counter}</Print>
<Button onClick={this.onClick}>+1</Button>
</Wrapper>
);
}
}
export default App;
버튼을 누르면 state의 counter 값이 +1씩 증가하게 하는 예제입니다.
onClick = () => {
this.setState({ counter: this.state.counter + 1 });
console.log(this.state.counter);
};
onClick 함수에서 setState로 state를 변경해주고 this.state.counter 출력 시 결과는 아래와 같습니다.
1이 출력되기를 기대했지만 예상과는 다르게 바뀌기 이전 값이 '0'이 출력되었습니다.
🤔 Why?
setState 함수는 비동기 함수이기 때문에 이벤트 핸들러 함수에서 바로 값을 갱신하는 것이 아닌 이벤트 핸들러 함수 종료 후 state값이 갱신됩니다.
✔️ 클래스형 컴포넌트의 setState Callback 사용법
<setState 함수의 정의>
setState<K extends keyof S>(
state: ((prevState: Readonly<S>, props: Readonly<P>) => (Pick<S, K> | S | null)) | (Pick<S, K> | S | null),
callback?: () => void
): void;
setState함수는 2개의 인자를 받는데 첫 번째 인자는 변경할 state를 전달하며, 두 번째 인자는 state가 변경된 후 실행되는 callback 함수를 전달합니다.
📋 코드
import React, { Component } from "react";
import styled from "styled-components";
import "./App.css";
const Wrapper = styled.div`
display: flex;
margin: 20px;
`;
const Print = styled.div`
border-radius: 5px;
border: 1px solid #6c757d;
width: 80px;
height: 30px;
font-size: 20px;
text-align: center;
`;
const Button = styled.button`
background-color: #6c757d;
border-radius: 5px;
border: 0px;
color: white;
width: 80px;
height: 30px;
margin-left: 10px;
&:hover {
background-color: #5a6268;
}
`;
class App extends Component {
constructor(props) {
super(props);
this.state = { counter: 0 };
}
onClick = () => {
this.setState({ counter: this.state.counter + 1 }, () => {
console.log(this.state.counter);
});
};
render() {
return (
<Wrapper>
<Print>{this.state.counter}</Print>
<Button onClick={this.onClick}>+1</Button>
</Wrapper>
);
}
}
export default App;
// function App() {
// return (
// <Wrapper>
// <Print></Print>
// <Button></Button>
// </Wrapper>
// );
// }
onClick = () => {
this.setState({ counter: this.state.counter + 1 }, () => {
console.log(this.state.counter);
});
};
따라서 위와 같이 state를 변경하고 callback함수로 변경된 state를 사용할 수 있게 됩니다.
✔️ 함수형 컴포넌트의 setState Callback 사용법
리액트 16.8 이전 버전에서는 함수형 컴포넌트에서 상태를 관리할 수 없었는데, 리액트 16.8 버전에서 Hooks라는 기능이 도입되면서 useState라는 함수를 사용하여 함수형 컴포넌트에서도 상태를 관리할 수 있게 되었습니다.
그러나 useState 함수의 경우 두 번째 인수가 존재하지 않기 때문에 userEffect를 사용하여 변경된 state를 사용해보겠습니다.
📋 코드
import React, { Component, useState, useEffect } from "react";
import styled from "styled-components";
import "./App.css";
const Wrapper = styled.div`
display: flex;
margin: 20px;
`;
const Print = styled.div`
border-radius: 5px;
border: 1px solid #6c757d;
width: 80px;
height: 30px;
font-size: 20px;
text-align: center;
`;
const Button = styled.button`
background-color: #6c757d;
border-radius: 5px;
border: 0px;
color: white;
width: 80px;
height: 30px;
margin-left: 10px;
&:hover {
background-color: #5a6268;
}
`;
function App() {
const [counter, setCounter] = useState(0);
const onClick = () => {
setCounter(counter + 1);
};
useEffect(() => {
console.log(counter);
}, [counter]);
return (
<Wrapper>
<Print>{counter}</Print>
<Button onClick={onClick}>+1</Button>
</Wrapper>
);
}
export default App;
useEffrct에서 두 번째 인자로 배열에 state를 넣어서 해당 state가 변경(업데이트)되면 useEffect 함수가 실행되도록 하였습니다.
🔎 useEffect 추가 설명
useEffect(() => {
console.log("마운트 될 때만 실행");
}, []);
useEffect(() => {
console.log("렌더링 될 때마다 실행");
});
useEffect(() => {
console.log("counter가 업데이트 될 때마다 실행");
}, [counter]);
'⚛️React' 카테고리의 다른 글
[React] 리액트 .js vs .jsx 차이점 (0) | 2022.03.18 |
---|---|
[React] 리액트 자식 컴포넌트에서 부모 컴포넌트로 데이터 전달하기 (2) | 2022.03.12 |
[React] 리액트 <select>에서 state로 defaultValue가 안먹힐 때 (1) | 2022.02.15 |
[React] 리액트 한줄에 4개씩 표시하기 (특정 개수 표시 후 줄바꿈, display:grid 사용) (0) | 2022.02.08 |
[React] 리액트 Hooks : useContext() 함수 사용법 (전역 상태 관리) (0) | 2022.01.09 |