게시글 작성 부분에서 포인트를 3개까지 추가하도록 구성하였는데, 내용을 다 작성하고 중간 포인트 input을 삭제한다면 3번째 input data가 날라가는 정확히는 리 렌더링으로 새로운 input이 씌어지는 현상이 있다.
적용하는 이유
게시글 작성에서 선택적으로 투자 포인트를 1 ~ 3개까지 작성 할 수 있도록 기획, 불필요한 textarea를 감추기 위해 버튼 onClick시 추가 textarea 생성하도록 함
문제 상황
3개의 투자 포인트를 작성 후 2번째 투자 포인트를 삭제 할 경우 3번째 투자 포인트 내용이 사라진다. react Developer & 개발자 도구 요소 창으로 확인해본 결과 3번째 textarea가 2번째로 바뀌면서 새로 작성된다.
원인 분석
내가 너무 안일한 생각을 했다. key값은 고유한 값이라 생각해 단순히 겹치지 않기 위해 [1,2,3]이란 배열을 만들어 key에 작성을 했는데, 이는 index와 다를 게 없었다. 결국 3번째 투자 포인트에 key값이 3에서 2로 변경되었기 때문에 리렌더링 시 같이 변경하게 됐다는 것을 파악했다.
해결 방법
-
투자 포인트를 마지막부터 삭제 할 수 있도록 변경
장점 : 별다른 추가 코드 없이 index로도 key값 설정이 가능하다.(기존 textarea위로 추가하는 방식은 없기 때문에)
단점 : 사용자 사용감이 떨어질 것 같다는 생각이 든다. 2번을 이상하게 쓰고 3번 내용이 좋을 때 중간에만 삭제할 수 없다....
-
DB Id값 처럼 순차적으로 늘어나는 고유의 key값을 만든다. 즉, 한번 생성했던 textare에서 사용한 key값을 재사용하지 않는다.
장점 : 1번 방법에 단점을 보완, 사용자의 편의성이 좋아진다.
단점 : 상태관리를 위해 useState를 추가해야한다. 이는 컴포넌트에 렌더링을 유발한다.
1번 방안 vs 2번 방안
우선 어떤 방법이든 2번 방안으로 선택 !
이유
- 투자 포인트 추가 삭제는 자주 발생하는 상황은 아니다. 크게 렌더링을 고려할 사항이 아니라 생각한다.
- 렌더링 최적화도 중요하지만 모든 프로젝트에 1번은 고객이다. 고객이 사용하기 편한 방법이 제일 중요하다 생각한다.
- 단점을 보완할 방법이 있다.
3번을 추가로 생각해보자면, 가장 먼저 든 생각은, textarea에 추가 state를 따로 자식 컴포넌트로 분리한다면 전체 렌더링을 막을 수 있다. 다만 지금 현재 상황에서 백엔드 로직에서 투자포인트를 작성하지 않아도 빈 문자열로 데이터를 보내야만 통과가 가능하다. 따라서 작성한 투자 포인트 중 하나라도 빈 칸이라면 전송하지 않고 경고를 띄워야 하지만, 총 몇 개를 작성했는지 알기 위해서는 결국 부모 컴포넌트에서 state관리를 해야한다.
더 고민을 해봐야 하겠지만, 개선 방법이 있을 것 같기 때문에, 2번 방법으로 진행하고자 한다.
추후 진행 상황
처음에는 onChange 이벤트로 input과 textarea를 관리했다.
const [countArr, setCountArr] = useState([{ key: 0 }]);
const [key, setKey] = useState(1);
상태로 고유한 key을 설정하기 위한 상태와 몇 개의 textarea를 표시 할 지 고유 key값을 가지고 있는 배열을 상태관리를 한다.
그리고 해당 key 배열만큼 ( textarea 수 만큼 ) 공백이 있는지 체크한다.
countArr.forEach((v, l) => {
if (
stockPoint[l]?.content === undefined ||
stockPoint[l]?.title === undefined ||
stockPoint[l]?.content === "" ||
stockPoint[l]?.title === ""
) {
state = true;
}
});
수정 된 코드는 onchange 대신 모든 textarea를 감싸고 있는 div태그에 useRef를 사용하여 관리했다.
변경한 이유로는 onchange로 textarea를 관리 했을 떄 불필요한 렌더링이 너무 많이 일어났고, debounce를 이용해 delay 타임을 주는 방법도 있지만 타이핑에 따라 변화할 요소가 없었다.
렌더링을 줄이고자 하위 컴포넌트로 분리를 했다. 그 상항에서 onchange를 사용하면 상태에 대한 의존도가 있기 때문에 렌더링 관점에서 별다른 개선이 없었고 ref를 이용해 렌더링에 영향을 줄였다.
이에 따라 textarea의 추가 삭제에 관한 렌더링은 textarea 컴포넌트에서만 동작을 하며, 유니크한 key값을 통해 최소화 하였고, ref를 통해 데이터 값을 보내기 때문에 form전체에 대한 렌더링 요소도 줄였다.
// ref
<div ref={choosePoint}>
{countArr.map((v, l) => {
return (
<WrapTextarea key={v.key}>
...
<input id={l} type="text" placeholder="투자포인트 요약" />
<TextareaText
name={l}
cols="30"
rows="5"
placeholder="상세내용 작성"
/>
</WrapTextarea>
);
})}
</div>
// api 요청
...
for (let i = 0; i < 3; i++) {
if (refArr[i] !== undefined) {
data["point" + String(i + 1)] = refArr[i].children[1].value;
data["content" + String(i + 1)] = refArr[i].children[3].value;
} else {
data["point" + String(i + 1)] = "";
data["content" + String(i + 1)] = "";
}
}
...
게시글 작성 부분에서 포인트를 3개까지 추가하도록 구성하였는데, 내용을 다 작성하고 중간 포인트 input을 삭제한다면 3번째 input data가 날라가는 정확히는 리 렌더링으로 새로운 input이 씌어지는 현상이 있다.
적용하는 이유
게시글 작성에서 선택적으로 투자 포인트를 1 ~ 3개까지 작성 할 수 있도록 기획, 불필요한 textarea를 감추기 위해 버튼 onClick시 추가 textarea 생성하도록 함
문제 상황
3개의 투자 포인트를 작성 후 2번째 투자 포인트를 삭제 할 경우 3번째 투자 포인트 내용이 사라진다. react Developer & 개발자 도구 요소 창으로 확인해본 결과 3번째 textarea가 2번째로 바뀌면서 새로 작성된다.
원인 분석
내가 너무 안일한 생각을 했다. key값은 고유한 값이라 생각해 단순히 겹치지 않기 위해 [1,2,3]이란 배열을 만들어 key에 작성을 했는데, 이는 index와 다를 게 없었다. 결국 3번째 투자 포인트에 key값이 3에서 2로 변경되었기 때문에 리렌더링 시 같이 변경하게 됐다는 것을 파악했다.
해결 방법
투자 포인트를 마지막부터 삭제 할 수 있도록 변경
장점 : 별다른 추가 코드 없이 index로도 key값 설정이 가능하다.(기존 textarea위로 추가하는 방식은 없기 때문에)
단점 : 사용자 사용감이 떨어질 것 같다는 생각이 든다. 2번을 이상하게 쓰고 3번 내용이 좋을 때 중간에만 삭제할 수 없다....
DB Id값 처럼 순차적으로 늘어나는 고유의 key값을 만든다. 즉, 한번 생성했던 textare에서 사용한 key값을 재사용하지 않는다.
장점 : 1번 방법에 단점을 보완, 사용자의 편의성이 좋아진다.
단점 : 상태관리를 위해 useState를 추가해야한다. 이는 컴포넌트에 렌더링을 유발한다.
1번 방안 vs 2번 방안
우선 어떤 방법이든 2번 방안으로 선택 !
이유
3번을 추가로 생각해보자면, 가장 먼저 든 생각은, textarea에 추가 state를 따로 자식 컴포넌트로 분리한다면 전체 렌더링을 막을 수 있다. 다만 지금 현재 상황에서 백엔드 로직에서 투자포인트를 작성하지 않아도 빈 문자열로 데이터를 보내야만 통과가 가능하다. 따라서 작성한 투자 포인트 중 하나라도 빈 칸이라면 전송하지 않고 경고를 띄워야 하지만, 총 몇 개를 작성했는지 알기 위해서는 결국 부모 컴포넌트에서 state관리를 해야한다.
더 고민을 해봐야 하겠지만, 개선 방법이 있을 것 같기 때문에, 2번 방법으로 진행하고자 한다.
추후 진행 상황
처음에는 onChange 이벤트로 input과 textarea를 관리했다.
상태로 고유한 key을 설정하기 위한 상태와 몇 개의 textarea를 표시 할 지 고유 key값을 가지고 있는 배열을 상태관리를 한다.
그리고 해당 key 배열만큼 ( textarea 수 만큼 ) 공백이 있는지 체크한다.
수정 된 코드는 onchange 대신 모든 textarea를 감싸고 있는 div태그에 useRef를 사용하여 관리했다.
변경한 이유로는 onchange로 textarea를 관리 했을 떄 불필요한 렌더링이 너무 많이 일어났고, debounce를 이용해 delay 타임을 주는 방법도 있지만 타이핑에 따라 변화할 요소가 없었다.
렌더링을 줄이고자 하위 컴포넌트로 분리를 했다. 그 상항에서 onchange를 사용하면 상태에 대한 의존도가 있기 때문에 렌더링 관점에서 별다른 개선이 없었고 ref를 이용해 렌더링에 영향을 줄였다.
이에 따라 textarea의 추가 삭제에 관한 렌더링은 textarea 컴포넌트에서만 동작을 하며, 유니크한 key값을 통해 최소화 하였고, ref를 통해 데이터 값을 보내기 때문에 form전체에 대한 렌더링 요소도 줄였다.