리액트에서 아주 중요한 부분이 있습니다
리액트에서 상태(state)를 변경하는데
해당 상태의 이전 값을 변경하는 경우
이렇게 작업해서는 안 됩니다
만약 상태를 이전 값에 기반하여
변경하는 경우
이 상태 업데이트 함수로 새로운 함수를 보내야 합니다
이것이 리액트가 추천하는 방식입니다
리액트 생태계에서는 이것이 최적의 방식이므로
이 방식을 기억해 두시기 바랍니다
상태를 이전 값에 기반하여 변경할 경우
함수를 하나 전달해야 하는데
해당 상태 변경 함수로 보내야 합니다
반환하고자 하는 새로운 상태값으로 보내면 안 됩니다
왜 함수를 보내야 할까요?
여기서 전달하는 이 함수를
리액트가 호출하여
자동적으로 현재 상태값을 가지게 되기 때문입니다
즉 상태 변경 전의 값이 입력됩니다
이 경우에는
매개변수를 하나 받는데, 이름은 editing으로 하겠습니다
이것 또한 true 혹은 false인데, isEditing과 동일합니다
하지만 이 매개변수는 값으로 인식되어
리액트가 함수 호출 시 동적으로 설정 및 전달하게 됩니다
이 함수를 setIsEditing으로 전달할 때
설정하고자 하는 새로운 상태를 반환하게 됩니다
여기에서 이미 언급한 느낌표를 사용할 수 있습니다
이대로 저장하고 확인해 보면
작동하는 방식은 이전과 같습니다
그러나 이 코드를 다시 보면
굉장히 장황해 보입니다
이 코드 또한 작동은 하지만 문제점이 있습니다
이 코드의 문제점은 바로
이 작업을 수행하는 리액트가
상태에 대한 변화의 스케줄을 조율한다는 점입니다
이것은 setIsEditing과 같은 상태 변경 함수를 통해 실행하므로
두 단계로 이루어집니다
즉 이 상태 변경은 즉각적으로 수행되는 것이 아니라
리액트가 미래에 수행하고자
상태 변경 스케줄을 조율하는 것입니다
이 시간은 몇 밀리초밖에 되지 않으므로
아주 빠른 시간이지만 즉각적이진 않습니다
이 차이가 중요합니다
리액트 개발자로서 이해해야 하는 중요한 점은
리액트가 이런 식으로 작업을 수행한다는 것입니다
이 작업방식을 이해하면
상태 변경 함수를 복사하고
바로 붙여넣는 작업을
첫 상태 변경 함수 직후에 수행할 때
왜 기대한 결과가 나오지 않는지 알 수 있습니다
일곱 번째 줄에서 볼 수 있듯이
setIsEditing이 현재 상태의 반대로 설정되어 있습니다
기본값이 false이므로 true로 설정되어 있는 것입니다
그리고 여덟 번째 줄에서는
직전 줄에서 setIsEditing이 true이므로
여기에서는 false로 변해 있는 것입니다
지금 이 임시 코드는
제가 설명을 위해 작성한 것인데
이 코드를 실행하면 아무 일도 일어나지 않습니다
setIsEditing을 true로 설정한 후 다시 false로 설정하기 때문에
버튼을 눌러도 아무 일도 일어나지 않습니다
이것이 우리가 예상하는 결과입니다만
이대로 저장 후 웹사이트로 돌아가 보면
예상한 결과와는 다른 것을 알 수 있습니다
수정 버튼을 누르면 입력 창이 정상적으로 뜨고
저장을 누르면 사라집니다
즉 이 결과는
이 두 번째 줄을 뺀 결과와 동일합니다
두 번째 줄을 빼도 입력 창이 뜨고 사라집니다
이것이 함수 형태를 사용해야 하는 이유입니다
이 부분의 코드를 보시면
리액트가 이 상태 변경 스케줄을 조율하는데
두 변화 모두 isEditing의 현재 상태를 기준으로 삼습니다
즉 시작점은 false입니다
그래서 일곱 번째와 여덟 번째 줄은
isEditing이 false인 시점을 기준으로 합니다
이 컴포넌트 함수가 처음 실행되는 시점에 isEditing의 값이
false이기 때문입니다
이 내장 함수는
생성될 당시
컴포넌트 함수 실행에 포함되어 있기 때문에
isEditing은 시작 시점의 값을 가지고 있습니다
setIsEditing을 isEditing의 반대격으로 호출할 때
상태 변경 스케줄을 조율하게 되는데
이때 setIsEditing을 true로 바꾸라는 명령이
즉각적으로 실행되지 않습니다
그 다음 줄에서도
이전과 동일한 상태가 유지됩니다
그 이유는 우리가 아직
동일한 컴포넌트 함수 실행의 사이클을
돌고 있기 때문입니다
그래서 여덟 번째 줄은 상태를 false로 바꾸지 않습니다
다만 true로의 동일한 업데이트를 스케줄합니다
그리고 이 두 상태 변화의 일정은
각자의 작업 이후에 실행됩니다
만약 우리가 이 함수 형태를 수정하여
이 상태를 변경한다면 상황은 달라집니다
두 경우 모두 이런 식으로 수정한다면
이대로 저장한 후에
버튼을 눌러도 아무 일도 일어나지 않습니다
이 때 처음으로 예정된 변화가
리액트에 의해 수정 상태에서 자동으로
가장 최신 버전의 상태값을 가져오는데
이 시점은 예정된 변경사항이 이미 실행된 때입니다
이 컴포넌트가 방금 렌더링되었으므로
이 값은 false가 됩니다
그리고 이후로 예정된 변경사항 또한
가장 최신 버전의 상태값을 가져오는데
이 시점 또한 예정된 변경사항이 실행된 때입니다
이 두 번째로 예정된 변경사항은
첫 번째로 예정된 사항 이후에 실행되기 때문에
리액트는 변경된 상태값을 전달하게 됩니다
이 경우에는 그 값이 true로
리액트가 실행한 결과값입니다
그러므로 여기에서 연습해볼 수 있는 것은
이 함수 형태를 사용해서
상태를 변경해 보는 것입니다
이 방식 말고 함수를 사용해 보는 것인데
함수 형태를 사용한다면
리액트가 보장해줄 수 있는 것은
이 상태값은 언제나
가장 최신 버전이라는 점입니다
그래서 이 부분은 필요하지 않지만
연습하는 데에 유용하고
기억하셔야 하는 부분은
상태 변경 시 이전의 상태값에
기반하여 변경한다면
이 함수 형태를 쓰셔야 합니다
바로 이 상태 변경 함수입니다
입력 창을 열고 닫을 수 있다는 점은 동일하지만
이것이 가장 효율적인 방식입니다