구현할 기능

위 기능을 구현하기 위해서는 todoItem들의 데이터를 State로 만들어서 보관해야 한다. 왜냐하면 새로운 데이터가 추가/수정/삭제되었을 때 화면에 변화를 반영할 수 있기 때문이다. State는 모든 자식 component에 전달해야하므로 조상 component인 app component에 만들어야 한다.
테스트 데이터로 각각의 아이템을 구별하는 id, 체크박스 유무를 나타내는 isDone, todo 컨텐츠를 보관할 content, 아이템이 언제 생성되었는 지를 알려주는 date 3가지 데이터를 mockData로 만든다. 그리고 useState를 mockData로 초기화 시켜준다.

추가버튼을 누르면 원하는 컨텐츠를 추가하는 기능을 하기 위해, onCreate 함수를 만들어준다. onCreate 함수는 content를 매개변수로 받아서 newTodo라는 객체의 content 값에 넣어준다.
todos의 값은 setTodos로 바꿔줘야하기 때문에 onCreate 함수 마지막에 setTodos 함수 안에 생성한 newTodo와 스프레드 연산자로 ...todos를 넣어주면 된다.
주의해야할 점은 todos.push(newTodo)이런 식으로는 절대 하면 안된다. 왜냐하면 todos라는 것은 상태여서 반드시 상태함수 setTodos로 값을 변경해야 리렌더링 되기 때문이다.
다음은 버튼을 클릭했을 때 생성한 onCreate 함수를 Editor 컴포넌트에 인수로 전달해준다.

입력받은 input 태그의 값을 저장할 State인 content와 입력값을 감지할 onChangeContent도 만들어준다. onSubmit를 만들어 onCreate 함수를 부르고 매개변수로 content를 전달한다. 버튼의 onClick 이벤트가 발생하면 onSubmit을 불러준다.

추가 버튼을 클릭하면 위와 같이 앞에 객체가 추가된 것을 볼 수 있다.

그리고 id값은 주민등록번호처럼 고유해야하는데, 지금은 0으로 동일하다. useRef를 이용해서 idRef를 만들어준다.

id의 값을 받아올 때 현재값 +1로 지정해주면 다음과 같이 id값을 저장할 수 있다.
onSubmit 함수 안에서 content값이 비어있으면 return 하게 해주면 된다.

contentRef를 하나 만들어주고, input 태그안에 ref로 지정해준다. 그리고 content가 비어있을 때 contentRef.current.focus()를 지정해주면 값이 비어있을 때 포커스해준다.

간단하게 추가되면 setContent("")를 추가해서 content값을 빈 문자열로 바꿔주면 된다.

onKeyDown이라는 이벤트 핸들러를 만들어주고, input 태그의 사용자가 키보드를 입력했을 때 발생하는 이벤트를 담당하는 onKeyDown에 연결해주면 된다. 우리가 작성한 onKeyDown 함수 안에서는 사용자가 엔터키를 눌렀을 때 입력이 되야하므로 조건문안에 e.keyCode == 13일 때 onSubmit()을 호출해주면 된다.


todos를 List component의 props로 전달하고, List component에서 받아온 todos를 map함수를 사용해서 content를 출력해준다.

위와 같이 저장된 todos의 content가 출력된다.

미리 만들어놓은 TodoItem component를 사용해서 저장된 todos의 데이터를 가져오려면, props로 ...todos를 전달한 후 TodoItem에서 받아서 사용하면 된다.

다음과 같이 출력된다.

콘솔창을 열어보면 다음과 같은 오류가 발생하는데, 이는 각각을 구분할 수 있는 key를 지정하지 않아서 그렇다.

해결하려면 key값으로 todo.id값도 넘겨주면 된다.

검색을 하면 리렌더링 되어야 하므로 검색도 state로 저장해야한다. 그리고 입력값을 받을 때마다 리렌더링 되어야하므로 onChangeSearch 함수를 작성해준다.

그리고 받은 검색을 찾을 getFilteredData 함수를 작성해준다. 함수는 받아온 search값을 todos에 있으면 반환해주는 역할을 한다.

toLowerCase로 모두 소문자로 변환해서 필터링해주면 다음과 같이 검색 기능을 구현할 수 있다.

App.jsx에서 onUpdate 함수를 작성해서 todos State의 값들 중에 targetId와 일치하는 id를 갖는 todo item의 isDone을 바꿔주면 된다.

List에 onUpdate를 전달해주고, 그것을 또 TodoItem으로 onUpdate를 전달해준다. TodoItem에서 onChangeCheckBox 함수를 만들어줘서 받은 onUpdate함수를 불러주면, 체크박스를 클릭할 때마다 isDone값이 바뀐다.

onDelete함수를 App.jsx에서 만들어서 todo 배열에서 targetId와 같은 id를 가진 todo만 삭제해서 새로 만들어서 반환해주면 된다.

onDelete 함수를 props로 List, TodoItem까지 전달한다. 그리고 TodoItem에서 onClickDeleteButton를 만들어서 onDelete를 불러주고, button에 onClick이벤트로 달아주면 된다.