Todo List 마저 구현하기
리듀서의 DONE 동작 구현
list 이외의 초기 state 값은 그대로 전달 되어야 하므로 전개 연산자를 꼭 사용해줘야 한다.
컴포넌트에서 전달 받은 id 값과 동일한 객체를 찾은 다음, 해당 객체의 done 항목을 true 로 변경해준다.
배열의 map() 메서드는 배열의 모든 값을 순회하면서 배열의 값을 return 된 값으로 변경해주기에 해당 메서드를 사용해준다.
//reducer
export default function todo(state = initState, action) {
switch (action.type) {
case CREATE:
return {
...state,
todoList: [
...state.todoList,
{
id: action.payload.id,
text: action.payload.text,
done: false,
},
],
nextId: action.payload.id + 1,
};
case DONE:
return {
...state,
todoList: state.todoList.map((e) => {
if (e.id === action.id) {
return {
...e,
done: true,
};
} else {
return e;
}
}),
};
default:
return state;
}
}
만들어준 리듀서를 컴포넌트에서 완료된 목록의 id 값을 받고 해당 목록의 done 키의 값을 true 해준다.
export default function TodoList() {
const list = useSelector((state) => state.todo.todoList).filter(
(e) => !e.done,
);
const inputRef = useRef('');
const dispatch = useDispatch();
const addTodo = () => {
dispatch(
create({
id: list.length,
text: inputRef.current.value,
}),
);
inputRef.current.value = '';
};
return (
<section>
<h2>할일 목록</h2>
<div>
<input type="text" ref={inputRef} />
<button onClick={addTodo}>추가</button>
</div>
<ul>
{list.map((e) => {
return (
<li key={e.id}>
{e.text}
<button onClick={() => dispatch(done(e.id))}>완료</button>
</li>
);
})}
</ul>
</section>
);
}
export default function DoneList() {
const list = useSelector((state) => state.todo.todoList).filter((e) => {
return e.done === true;
});
return (
<section>
<h2>완료된 목록</h2>
<ul>
{list.map((e) => (
<li key={e.id}>{e.text}</li>
))}
</ul>
</section>
);
}
같은 키를 가진 경우
리스트 요소의 key 값은 고유해야 하므로 발생하는 경고
즉, todoList 에서 할일을 추가할 때 store 에서 받아온 list 의 length 값을 넘기고 -> 이미 완료를 하면 리스트의 길이가 짧아지고, 새로 생성되는 <li> 요소는 이전의 key 와 동일한 값을 가지게 되므로 발생!
할일 목록 id 를 목록의 순번으로 부여하고 있으므로 해당 순번을 store 에서 전역으로 관리하여 문제를 해결할 수 있다.
let counts = initState.todoList.length;
initState['nextId'] = counts;
switch (action.type) {
case CREATE:
return {
...state,
todoList: [
...state.todoList,
{
id: action.payload.id,
text: action.payload.text,
done: false,
},
],
nextId: action.payload.id + 1,
};
리스트의 길이로 key 를 관리하는 것이 아닌, nextId 값을 todo.js 모듈에서 처리 후 받아준다.
const nextId = useSelector((state) => state.todo.nextId);
const addTodo = () => {
dispatch(
create({
id: nextId,
text: inputRef.current.value,
}),
);
inputRef.current.value = '';
};
key 값을 어떻게 처리할지가 중요한 것 같다.
'학원에서 배운 것 > React' 카테고리의 다른 글
KDT 5th 웹개발자 입문 수업 44일차 (0) | 2023.04.06 |
---|---|
KDT 5th 웹개발자 입문 수업 43일차 - 2 (0) | 2023.04.05 |
KDT 5th 웹개발자 입문 수업 42일차 (0) | 2023.04.04 |
KDT 5th 웹개발자 입문 수업 41일차 (0) | 2023.04.03 |
KDT 5th 웹개발자 입문 수업 40일차 (0) | 2023.03.31 |