해야할 것
- 헤더에 있는 체크박스가 클릭되면
type
을 all
로 받아서 헤더의 체크박스와 직원목록의 전체 체크박스 on/off
가 되면서 데이터도 반환되어야 한다.
- 헤더의 체크박스가
on
일 때(즉, 전체 직원목록의 체크박스가 on
상태), 개별 직원의 체크박스가 off
되면 헤더의 체크박스가 off
되고, 다시 개별 직원의 체크박스가 on
되면 헤더의 체크박스가 on
되어야 한다.
- 누를 때마다 동작해야 하니까 데이터를 넣어주는 부분에서 핸들링 한다.
안 됐던 부분
- 데이터를 넣어주는 부분이
cm.staffCheckedData
라는 함수인데 이 함수는 전체적으로 사용하는 것이기 때문에 다른 곳에 빠져있었다. 즉, staffChecked
-> cm.staffCheckedData
라는 한 depth가 더 있는 것이라 cm.staffChecked
에서 반환되는 resultData
와 staffChecked
페이지의 staffCheckedList
가 바로바로 동기화되지 않았다.
- 내가 하려고 했던 건
each
체크박스를 클릭할 때 조건문으로 전체 인원수인 userCnt
와 resultData
의 숫자가 같으면 헤더의 전체 체크박스를 켜고 아니면 켜지 않는 식으로 컨트롤 하려고 했다.
- 그런데,
staffCheckedList
가 한 박자 늦게 동기화가 되니까 이게 원하는대로 동작하지 않았다.
어떻게 했는지
- 사수분께 질문했더니,
setState
는 값이 '언젠가' 바뀌는 것을 보장하는 것이지 그 즉시 바뀌는 것은 될 수도 있고 안 될 수도 있는 거라고 했다. 그래서 async/await
도 가급적이면 안 쓰는 게 좋다고 리액트 측에서 얘기했다고도 버전 18부터는 이제 무조건 보장 안 해 줄 거라고 했단다.
if (type !== 'all') {
const staffData = this.state.staffCheckedData ? this.state.staffCheckedData : null;
const staffCheckedData = cm.staffCheckedData(events, staffData, targetChecked, 'each');
if (staffCheckedData.length === this.state.userCnt) {
$('.allCheckbox').prop('checked', true);
} else if (staffCheckedData.length !== this.state.userCnt) {
$('.allCheckbox').prop('checked', false);
}
this.setState({
staffCheckedData
});
}
- 그래서
if
문 안에서 staffCheckedData
라는 지역변수를 선언하고 거기다가 cm.staffCheckedData
함수를 돌려서 그 resultData
를 값으로 받아놓은 뒤, 그것을 setState
로 데이터를 셋팅시켰다. setState
의 값이 바로 바뀌지 않기 때문에 그 변경되는 값을 바라보고 무언가를 해야한다면 이런 식으로 변수를 선언해서 값을 얻어낸 다음 그걸 셋팅시키는 것이 맞다고 한다.
배운 점
- setState 는 값이 '언젠가' 바뀌는 거지 지금 당장 바뀌는 건 보장이 안 되니까 그냥, "setState 는 바로 안 바뀐다" 고 생각하고 개발하는 게 더 나을 거라는 조언을 들었다.
- 그리고 개발되어 있는 것을 운영보수 하고 있는 거라 코드에 대한 별 생각은 없었는데(어떻게 하면 원하는 대로 고칠 수 있을지만을 생각함) 사수분이 말해주시기를, 리액트 안에서 jQuery 나 querySelector 로 핸들링 하는 개발은 지양해야 되는 거라고 했다. 지금 당장 컨트롤 하기는 훨씬 쉽기는한데 나중에 에러같은 거 찾아내는 디버깅 할 때 지금처럼 힘들다고... 시간이 더 들고 공수가 들어도 처음부터 리액트로 동작하게 만들어야 된다는 걸 주지하라고 하셨다.