렌더링, 화면에 변화를 보이다
렌더링 이란 웹 페이지상에서 해당 페이지의 구성요소를 조립하여 사용자에게 보여주는 행동이다.
p 태그안에 state.name변수를 나타내도록 하고
버튼을 클릭하면 온클릭 이벤트로 name변수를 new로 변경하도록 해본다.
예상대로라면 name변수가 old에서 new로 변경되니
Hi new의 문장으로 변경되어 표현될 것이다.
하지만 버튼을 아무리 눌러도 name변수는 new로 변경되지만
화면의 old는 변경되지 않는다.
SPA를 위한 React의 렌더링은 임의의 상태가 변화할 때 Re-rendering을 하여 변동사항을 갱신하여 보여준다.
분명 클릭이벤트로 인해 name변수는 new로 변경이 되었는데 왜 리렌더링이 일어나지 않았을까
Re-rendering이 일어날 조건과 변수의 메모리공간
one변수를 선언하고 1의 값을 할당한 후, two변수엔 one을 할당했다.
one변수와 two변수에 1을 할당했다.
이후 두 변수를 비교해보니 두 케이스 모두 일치한다.
Call by value인 변수인 one과 two는 타입과 값이 일치하기에 같다고 나온다.
이번엔 각 변수에 객체타입을 할당하여 두 케이스 모두 비교해봤다.
two에 one을 대입할때는 마찬가지로 같다고 나오지만
같은 값으로 보이는 {num:1}을 할당하고 비교하니 false가 나온다.
Call by reference는 메모리 저장공간에 대한 값을 가진다. 따라서 첫번째 케이스와 같이 대입을 하면 값과 주소를 동일하게 가져가지만 두번째는 주소공간이 다르기에 값이 같아도 다른 취급을 받는다.
변수 two에 one을 대입한 경우 값과 주소를 동일하게 가진다.
따라서 one.num에 2를 대입하면 two객체의 num도 2로 변경되게 된다.
그렇다면 여기서도 name이 new로 변경이 되었는데도 리렌더링이 일어나지 않은 이유는
값만 바뀌었을 뿐이지 주소값까진 변경되지 않아서라고 볼 수 있다.
React의 리렌더링은 상태값이 완전히 새로운 주소와 값을 가질때 일어난다.
따라서 값을 그저 대입을 하면 같은 주소를 가지기 때문에 name변수가 변경되어도 화면에 나타나지 않는다.
SetState
위와 같은 문제는 setState를 사용하면 해결된다.
버튼을 누르면 name이 완전히 다른 상태로 변경되었다 생각되어
rerendering하여 변경된 new를 나타내게 된다.
setState는 타겟된 name값만 변경하고 age는 변경하지 않는다.
old에서 new만 변경될 뿐 20의 값은 그대로이다.
Shallow merge
name의 기본값이 first와 last를 가지는 객체라도 setState를 통해 name만 주어졌다면
기존의 값을 지우고 새로운 값으로 대입된다.
p태그안의 양식에는 this.state.name이 없으므로 아무것도 나타나지 않는다.
asynchronous, Callback
버튼을 누르면 setState와 console.log가 같이 동작하도록 해뒀다.
여기서 이상한 것은 변경된 값인 new가 출력되는 것이 아닌 이전값인 old가 콘솔창에 찍힌다는 것이다.
이는 setState의 변경보다 콘솔명령이 먼저 실행된다는 것을 의미한다.
버튼을 한번 더 눌러보면 확실히 알 수 있다.
콜스택에서 콘솔명령이 모두 실행된 뒤에 setState가 비동기로 실행되어 값을 변경하고 렌더링이 되는 것이다.
따라서 그 이후의 콘솔에는 변경된 값이 출력된다.
setState의 두번째 인자에 콜백함수를 정의할 수 있다.
콜스택에서 작동하던 콘솔로그를 콜백함수로 호출해본다.
변경된 new가 바로 콘솔에 출력되게 된다.