카테고리 없음

[트러블 슈팅] useState 훅에 함수를 전달해서 동기적으로 작동하는 것처럼 보이게 해보자

아보카도 있었어! 2023. 4. 14. 23:43

입력값이 있어도 빈 값이라는 메시지가 alert된다

handleSubmit을 다시 보자.

localState의 길이를 기준으로 0인지 아닌지를 판단하여 분기 처리하고 있다.

검색창에 입력값 'a'가 있음에도 아직 setLocalState가 반영되지 않았기 때문에, handleSubmit 함수가 호출돼서 입력값이 비었는지 확인하는 유효성 검사에서 빈 값(length === 0)으로 판정되어 'Please Enter github name.'이라는 메시지가 alert된다.

반면, input dom에 바로 접근하는 inputValue는 입력값을 그대로 반영한다.(53째 줄에 입력값 그대로의 검색 결과를 받아오기 위해 인수로 전달)

그 결과 다음과 같은 메시지가 콘솔에 출력된다.

 

inputValue: a, localState: ' '(빈 값)

 

왜 이런 현상이 발생한 것인지 setLocalState의 호출부를 가 보면 알 수 있다.

 

 

setLocalState와 비동기 api 요청 함수 handleSubmmit 이 같은 스코프 안에서 호출되고 있다.

 

그러면 state는 언제 업데이트 되는 것일까? 모른다. setState는 비동기함수이기 때문이다.

LocalState값 변경은 비동기적으로 일어나기 때문에, 그 아래 코드들은 그대로 실행되어 handleSubmit 함수를 호출하고, 아직 변경되지 않은 LocalState의 빈 값을 그대로 가져와서 실제 검색창에 입력 값이 있음에도 빈 값으로 판정되어 처리되는 것이다.

 

1. 그렇다면, LocalState가 변동되었을 때 handleSubmit 함수를 호출하면 어떨까?

 

useState 변수로 관리하고 있는 localState에 변동이 일어났을 때 handleSubmit 함수를 호출하면 되므로, useEffect() 등으로 처리할 수도 있다.

 

https://codingapple.com/unit/react-setstate-async-problems/

 

2. useState 훅을 동기적으로 작동시킬 수는 없을까?

 

useState 훅에 콜백함수를 전달하면 된다.

해당 콜백함수 안에서 handleSubmit 함수를 호출하면 변동된 값을 인수로 전달할 수 있다. (위 이미지에서 스코프만 달라졌다.)

 

콜백함수 안에서 handleSubmit 호출하기

 

34째 줄에서 첫 번째 인수의 값을 `null`로 전달하는 이유는 handleSubmit이
이벤트 객체를 받아 처리해야 하거나(정상적으로 검색 버튼 클릭, 엔터 등으로 'submmit'이벤트가 발생)
이벤트 발생없이 실행되어야하는 경우(타이핑을 끝내자마자 검색결과를 출력)

모두를 처리하고 있기 때문이다.

 

옵셔널체이닝으로 두 경우에 대한 예외처리를 했다.

60째 줄의 searchUsers는 삼항연산자로 타이핑일 경우와 submit 이벤트 발생일 경우로 분기 처리했다.

inputRef를 전달하지 않아도, 바뀐 상태의 값으로 호출을 잘 해오는 것을 확인할 수 있다.

 

타이핑과 submit 둘다 검색결과를 받아온다

 

lcoalState가 늦게 동기화되는 현상은 동일하다

위 이미지와 같이 여전히 inputRef.current.value 값과 변수 localState의 값은 동일하지 않지만, 요청을 새로 바뀔 값으로 보내고 있으므로 더 이상 입력값에 값이 있어도 늦은 동기화 때문에 빈 값으로 인식하고 잘못된 요청을 보내는 경우는 없다.