리액트 기초/라이프사이클 + State 관리
단방향 데이터 흐름, setState()
덕구공
2021. 7. 14. 21:37
단방향 데이터 흐름
데이터는 위에서 아래로, 즉, 부모 컴포넌트에서 자식 컴포넌트로 넘어간다.
부모 컴포넌트의 state가 업데이트 되면 자식 컴포넌트도 리렌더링
이 일어난다.- 만약 자식 컴포넌트가 부모 컴포넌트의 state를 고칠 수 있다고 가정하면, 부모 컴포넌트는 state가 변했으니 렌더링이 일어나고 부모가 렌더링이 일어나면 자식도 렌더링이 일어난다. 이 과정이 반복되면 무한 루프에 빠져버려 노답이된다.
이런 경우가 생기지 않게 하기 위해서 무조건 데이터는 단방향으로 흐르는 것을 알아야 하고 부모만 자식을 변경해야 한다!
왜 setState() 함수를 사용할까?
- 예를 들어
어떤 리액트 요소를 클릭했을 때, 컴포넌트의 state 값이 변경되도록 하려고 아래처럼 이벤트를 포함하는 코드를 작성했다고 하자.
import React from 'react';
import './App.css'
class App extends React.Component{
constructor(props){
super(props);
this.state = {
duck: 1
}
}
render(){
return(
<div className="App" onClick={function(){
this.state.duck = 2;
console.log(this.state.duck);
}.bind(this)} style ={{background: 'blue'}}>
<h1>{this.state.duck}
</h1>
</div>
);
}
}
export default App;
- 위 코드를 실행시켜보면
리액트 요소를 클릭했을 때, 이벤트 함수가 this.state.duck = 2 로 state 값을 1에서 2로 변경시켜서 콘솔창에 2가 찍혀도 화면에 나타나는 값은 변하지 않는 것을 알 수 있다.
리액트가 state 값이 바뀌었다는 것을 모르기 때문이다.
- 이를 해결하기 위해서
setState를 사용하면 UI와 state가 동시에 정상적으로 업데이트된다.
import React from 'react';
import './App.css'
class App extends React.Component{
constructor(props){
super(props);
this.state = {
duck: 1
}
}
render(){
return(
<div className="App" onClick={function(){
this.setState({duck: 2});
}.bind(this)} style ={{background: 'blue'}}>
<h1>{this.state.duck}
</h1>
</div>
);
}
}
export default App;
setState()
클래스형 컴포넌트에서 state를 관리하는 방법.
- 아래처럼 중괄호 안에 변경할 state 요소와 할당할 값을 json 형식으로 key: value 쌍으로 넣어준다.
this.setState({[변경할 state 요소]: [할당할 값]})
- 예를 들어, duck이라는 state의 값을 4로 바꾸면 아래처럼 사용하면된다.
this.setState({duck: 4})
- 만약
render() 함수 바로 아래에 이벤트 없이 setState()를 사용하면 무한루프가 발생
한다. setState() 호출하면 render()함수가 실행되기 때문이다!
import React from 'react';
import './App.css'
class App extends React.Component{
constructor(props){
super(props);
this.state = {
duck: 1
}
}
render(){
this.setState({duck: 2});
return(
<div className="App" style ={{background: 'blue'}}>
<h1>{this.state.duck}
</h1>
</div>
);
}
}
export default App;
- 아래처럼 이벤트와 같은 것을 사용해서 달아서 조건에 따라 setState가 실행되도록 하자.
import React from 'react';
import './App.css'
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
duck: 1
}
}
hi = () => {
this.setState({ duck: 4 });
}
render() {
return (
<div className="App">
<button onClick = {this.hi}>state 변경</button>
</div>
);
}
}
export default App;
주의사항!!!
만약 state를 변경하는 함수에 ()를 붙이면 무한루프에 빠지게 된다!
- 아래의 경우
hi()가 state를 변경하는 setState를 포함하는 함수라 가정하면 아래처럼 ()를 붙여서 사용하면 함수를 호출한 것이므로 요소가 렌더링 되자마자 함수가 호출이 된다!
<button onClick = {this.hi()}>state 변경</button>
- 아래처럼 단순히
함수를 선언해서 bind
하거나
<button onClick = {function(){this.hi()}.bind(this)}>state 변경</button>
- 아래처럼
()를 떼어서
함수를 참조하면 무한루프
에 빠지지 않는다!
<button onClick = {this.hi}>state 변경</button>