이전 챕터에서는 mode
라는 state
값을 직접 바꾸는 코드를 사용할 때 에러가 발생한다는 것을 알게 되었다.
이 에러를 해결하기 위해서는 this.setState()
함수를 사용했다.
왜 이런 함수를 거쳐야 하는지 알아보자.
컴퍼넌트 생성이 끝난 후 동적으로 state
의 값을 바꿀 때 this.state.mode = 'welcome'
처럼 코드를 작성하면 안된다.
this.setState()
라는 함수를 통해 변경하고 싶은 값을 객체 형태로 넣어주는 것을 통해서 state
값을 변경해야 한다.
그 이유는 this.state.mode = 'welcome'
으로 값을 바꿀시 리액트 입장에서는 몰래 바꾼 셈이기 때문이다.
즉, 리액트 모르게 값이 바뀌었으므로 렌더링을 할 수 없는 것이다.
에러가 발생하는 예
<header> <h1> <a href='/' onClick={function (e) { console.log(e); // 이벤트 매개변수 e 출력 e.preventDefault(); // a 태그의 동작을 금지함 this.state.mode = 'welcome'; // 오류 : 리액트가 알지 못함 // state mode 변경 // this.setState({ // mode: 'welcome' // }); }.bind(this)}>{this.state.subject.title} </a> </h1> {this.state.subject.sub} </header>
위 코드 작성 후 링크를 클릭했을 때 state / "mode"
의 값이 바뀌었다는 것을 리액트가 알고 있다면
render()
함수가 호출되고, 이 컴포넌트의 하위 컴포넌트들 또한 호출이 되면서 우리가 작성한 console.log
에 출력이 될 것이다.
그리고 웹 브라우저의 본문 내용도 "welcome"에 해당하는 내용으로 바뀔 것이다.
하지만 링크를 클릭하여 state
값을 변경시키더라도 콘솔 창에는 아무것도 출력이 안되고, 화면도 바뀌지 않는다.
state
의 값이 "welcome"으로 바뀌었지만 리액트는 알지 못하고 그로 인해 원하는 결과를 얻지 못하게 된다.
올바른 예
<header> <h1> <a href='/' onClick={function (e) { console.log(e); // 이벤트 매개변수 e 출력 e.preventDefault(); // a 태그의 동작을 금지함 // this.state.mode = 'welcome'; // 오류 : 리액트가 알지 못함 // state mode 변경 this.setState({ mode: 'welcome' }); }.bind(this)}>{this.state.subject.title} </a> </h1> {this.state.subject.sub} </header>
위 코드와 같이 setState()
함수를 사용하도록 바꾸게 되면 setState()
함수가 호출되면서 내부적으로 많은 일들을 수행하게 된다.
constructer()
함수 안에 있는state
값을 직접 입력해 바꿀 수 있지만state
의 값이 변경되면setState()
함수를 이용해서 바꿔야 한다