React

[React] onChange 값이 한 박자씩 늦게 들어갈 때 / observable 변수 렌더링 뒤늦게 반영될 때

빡새 2023. 1. 2. 08:00

- 사용 기술 -
React(class형) / mobx

 


-  상황 설명 -

Select1    |   Select2    |   Input
type1       |   type2       |   title

폼이 있다.
폼 안에는 요소가 총 세 개 있다.
select 두 개와 input 하나가 있다.
이 모든 요소들은 값이 store 에 있는 data와 바인딩되어 있다.
select1  data.type1 과, select2 는 data.type2 와 바인딩해 놓았다.
input 은 data.title 과 바인딩해 두었다.

<Select1 value={data.type1} />
<Select2 value={data.type2} />
<Input value={data.tile} />



select 에는 각각 이벤트가 걸려 있다.
값이 바뀌면 onChange 이벤트가 발생한다.
받아주는 함수 내용은 두 가지다.

첫째로 store 가 들고 있는 data 에 값을 넣어준다.
key-value 쌍으로 넣어주는데 data[key] = value 형태다.
select1 의 값은 data 에 type1 이라는 key 로 넣어주고,
select2 의 값은 data 에 type2 이라는 key 로 넣어준다.
data.type1 = select1.value;
data.type2 = select2.value;

둘째로 Input 에 들어갈 title 값을 포맷팅한다.
포맷팅은 아래처럼 한다.
Select1 의 출력값을 받아온다.
그리고 Select2 의 출력값과 이어붙인다.
그 결과를 data 에 title 로 넣어준다.
그러면 data.title 과 바인딩되어 있는 Input 안에 값이 들어간다.
data.title = `${data.type1}_${data.type2}`;



- 문제 상황 -

Input 에 data.title 이 제대로 들어가지 않았다.
들어가긴 들어가는데 한 박자씩 늦게 들어갔다.
Select 값이 바뀌면 새로 바뀐 값들을 가지고 title 이 만들어져야 하는데
바뀌기 이전의 값들을 가지고 title 이 Input 에 들어갔다.

예를 들어 이렇다.
Select1    |   Select2     |   Input
hello1      |   world1      |   
위에서 아래로 select 값들이 바뀌었다고 해 보자.
Select1    |   Select2     |   Input
hello2      |   world1      |   


그러면 Input 값에는 "hello2_world1" 이 들어가기로 예상했다.
그러나 실제로는 "hello1_world"가 들어가 있었다.
이상한 점은 이 상태에서 막상 props 를 출력해 보면
data.title 에는 예상했던 값인 "hello2_world1" 가 제대로 들어있었다.


Input 에는 data.title 을 바인딩해 두었고,
data.title 에는 "hello2_world1" 가 제대로 들어있었다.
그런데도 Input 에는 "hello1_world1" 가 들어가 있었다.
Select1 을 "hello1" 에서 "hello2"로 바꾸면 
Input 값도  "hello1_world1" 에서  "hello2_world1" 로 바뀌어야 하는데
"hello1_world1" 이 들어있었다.
"hello2" 에서 "hello3"으로 바꾸면 "hello2_world1" 가 들어갔고,
"hello3" 에서 "hello4"으로 바꾸면 "hello3_world1" 가 들어갔고,
한 박자씩 늦게 들어간다는 말은 바로 이 뜻이다.


- 원인 -

data 객체에 해당  keyvalue 로 값이 선언되어 있지 않았기 때문이다.
무슨 말이냐면, 로직이나 문법이 문제가 아니라 store 가 들고 있던 data 를 어떻게 초기화해주느냐가 문제였다.
초기화하는 data 의 내부 구조에 따라서 의도한 대로 작동할 수도 있고 아닐 수도 있다.
data = {typ1: "", type2: ""};
만약 data 를 초기화할 때 값이 위처럼 "title" 키가 아예 존재하지 않는 구조라면
"title" 에 바인딩된 요소는 값이 한 박자씩 늦게 들어간다.
반면에 아래처럼 그 안에 "title" 키가 선언되어 있고 
어떤 값이든 들어가 있다면 Input 에  title 값이 의도한 대로 들어간다.
data2 = {type1: "", type2: "", title: ""};

 

- 참고 -

> 참고1: react 에서 state 를 초기화하거나 업데이트할 때도 비슷한 이슈가 있었던 거 같은데 자료를 찾지 못했다. 찾으면 덧붙여서 업로드해야겠다.
> 참고2: event handler 를 통해서 store 에 값을 넣어줄 때, data[key] = value 로 넣어주고 있었다. 이 문법 때문이 문제일지도 모른다는 생각이 들었다.
기존의 객체는 그대로 두고 해당 key 에 value 만 새로 꽂아주는 형태인데, 아예 새로운 객체를 넣어주는 문법을 써도 같은 문제가 발생하는지 시도해봐야겠다.
data = {...this.data, [key]: value}

-221213




반응형