개발자

리액트 투두리스트 체크박스

2024년 05월 02일조회 75

리액트로 투두리스트를 만들어보고 있는데 삭제 기능은 filter() 메서드로 구현하였고, 체크박스는 input에 css :checked로 구현하였습니다. 문제는 첫번째 항목을 체크하고 난 후에 리스트 앞부분에 새로운 항목을 추가해도 체크박스는 항상 첫번째 항목에 체크되어 있습니다... 인풋 박스를 독립적으로 빼서 컴포넌트로 사용하면 개별로 적용될거 같았는데 결과는 같았고, state로 체크 된 항목을 따로 관리해봤는데 그거또한 결과가 같았습니다...ㅠㅠ 리스트의 key는 map의 index로 사용하고 filter()로 삭제 기능을 구현하니 키는 마지막 순서만 삭제되면서 재렌더링으로 리스트가 변경되서 체크박스가 개별로 적용이 안되는것으로 예상이 됩니다만 너무 어렵네요ㅠ.. 구체적으로 도와주시면 감사하겠습니다ㅠㅠㅠ코드는 첨부했습니다!

1import { React, useCallback, useContext, useState } from 'react';
2import todoListFrame from"./TodoListFrame.module.css";
3import { ListSetContext } from '../context/ListSetContext';
4
5function TodoListFrame() {
6  const {todoList, setTodoList} = useContext(ListSetContext);
7
8  const onDelete = useCallback((index)=>{
9      setTodoList((prev)=>prev.filter((_,listId)=>listId !== index))  
10  },[]);
11
12  return (
13    <div className={todoListFrame.listFrame}>
14      {todoList.map((content,index)=>{
15        return(
16          <li key={index} className={todoListFrame.listItem}>
17            <input type='checkbox' className={todoListFrame.checkBox}/>
18            {content}
19            <button className={todoListFrame.delBtn} onClick={()=> onDelete(index)}>❌</button>
20          </li>
21        )
22    })}
23    </div>
24  );
25}
26
27export default TodoListFrame;
이 질문이 도움이 되었나요?
'추천해요' 버튼을 누르면 좋은 질문이 더 많은 사람에게 노출될 수 있어요. '보충이 필요해요' 버튼을 누르면 질문자에게 질문 내용 보충을 요청하는 알림이 가요.
profile picture
익명님의 질문

답변 1

뱀부님의 프로필 사진

todoList에 시퀀스 넘버등의 고유 id를 넣고 key에 index 대신 그 id를 넣어줘보세요 왜 그렇게 동작하는지에 대한건 이 글이 도움이 될 것 같습니다 https://velog.io/@jay/do-you-know-ui-tree

profile picture

익명

작성자

2024년 05월 03일

헉 감사합니다ㅠㅠ정말 많은 도움되었습니다!!

지금 가입하면 모든 질문의 답변을 볼 수 있어요!

현직자들의 명쾌한 답변을 얻을 수 있어요.

또는

이미 회원이신가요?

AI 답변
커리어리 AI 봇 프로필 이미지

커리어리 AI 봇

GPT가 달아주는 답변입니다.

2024년 05월 02일

코드를 보니, 체크 상태를 표현하는 state를 만들어 각 항목이 체크되었는지 관리하도록 수정해야 할 것 같습니다. 또한, map 함수에서 사용하는 key의 값을 고유하게 유지해야합니다. map의 index를 key로 사용하는 것은 권장되지 않습니다. 이는 단순히 배열의 순서만 의미하기 때문에, 배열에 변화가 생기면 원치 않은 결과를 초래할 수 있습니다. 다음은 각 항목에 대한 체크 상태를 관리하는 예제 코드입니다: ```javascript import { React, useCallback, useContext } from 'react'; import todoListFrame from "./TodoListFrame.module.css"; import { ListSetContext } from '../context/ListSetContext'; function TodoListFrame() { const {todoList, setTodoList} = useContext(ListSetContext); const onDelete = useCallback((id)=>{ setTodoList((prev)=>prev.filter((item)=>item.id !== id)) },[]); const onToggle = useCallback((id)=>{ setTodoList( todoList.map(item => item.id === id ? {...item, checked: !item.checked} : item, ), ); },[todoList]); return ( <div className={todoListFrame.listFrame}> {todoList.map(({id,content,checked})=>{ return( <li key={id} className={todoListFrame.listItem}> <input type='checkbox' checked={checked} onChange={() => onToggle(id)} className={todoListFrame.checkBox}/> {content} <button className={todoListFrame.delBtn} onClick={()=> onDelete(id)}>❌</button> </li> ) })} </div> ); } export default TodoListFrame; ``` 위의 코드에서는 todoList 각각의 아이템에 고유한 id와 checked라는 state가 추가되었습니다. 이제 체크박스는 항목별로 독립적으로 작동하게 됩니다. 또한, 삭제 기능은 고유한 id를 이용해 특정 항목을 삭제하도록 수정되었습니다. (tag기반으로 id를 생성하는 방법이나 다른 고유id 생성 라이브러리를 사용하면 좋습니다.)

목록으로

지금 가입하면 모든 질문의 답변을 볼 수 있어요!