내용 목차
React todo list 프로젝트 순서
- 먼저 <form>태그를 만든다. 그 안에 input 박스와 button을 만들 것이다.
- Todo List를 입력받을
<input type="text" value="">
박스를 만든다. - <input>에서 입력한 값을 받을 변수를 useState를 이용해 만든다.
const [todo,setTodo] = useState()
- 만들어진 todo 변수를 input의 value 속성의 값으로 넣는다.
<input value={todo || ''} type='text' />
(value코드 안에||''
는 넣지 않아도 된다. 자꾸 콘솔에서 경고 문구가 나타나서 넣었다.) - <input> 박수 안에서 글이 쓰여지는 것을 감지해서 값이 변화되면 그 값으로 todo 변수의 값을 수정한다. 즉, onChange 이벤트리스너를 단다.
<input onChange={onChange} value={todo} type="text" />
- onChange 이벤트 리스너 함수를 만든다.
const onChange = (e) => setTodo(e.target.value);
- <button>태그를 넣는다.
<button>Add todo</button>
- input 박스에 값을 넣고 엔터치면 <form>이 활성화 되면서 화면이 다시 refresh된다. 이것을 막고, 공백 상태에서 엔터를 계속 입력해도 값이 입력되지 않도록 하고, 또한 일단 값을 넣고 엔터를 입력하면 다시 입력할 수 있도록 input 박스를 비우도록 하는 코드를 만들어야 한다. 이것을 <form>에 onSubmit 이벤트리스너를 설치해서 만든다.
<form onSubmit = {onSubmit}>
- 방금 만든 onSubmit 리스너 함수를 만들어 주자.
const onSubmit = (e) => {...}
- 입력한 todo 값을 배열로 저장 해줘야 한다. 그러기 위해서 배열 변수를 하나 만든다.
const [todos, setTodos] = useState([]);
- onSubmit()함수 안에서 todo가 들어올 때마다 todos 배열에 더해 줘야 한다. 하지만 react에서는 todos.push(todo)처럼 직접적으로 todos를 수정할 수 없다. 그래서 setTodos를 이용한다. 그리고 배열에 추가하는 방법도 spread operator를 이용할 것이다.
setTodos(item => [...item, todo]);
- 입력부분과 출력부분을 구분하기 위해 <hr /> 한번 넣어주고…
- ※ React의 JSX에서 바닐라 자바스크립트를 넣고 싶으면 {}안에 넣으면 된다.
- 리스트로 만들기 위해 <ul></ul>태그를 넣어준다.
- ul 태그 안쪽에 자바스크립트로 li 태그를 자동으로 만들 것이다. map()함수를 이용한다. li에서 key 속성을 넣은 이유는 React에서 자꾸 넣으라고 해서 메세지가 떠서…
todos.map((item,idx) => <li key={idx}>{item}</li>)
- 여기까지 얼추 다 만들어졌다.
- 그런데 삭제 버튼도 만들고 싶다면 <li> 안에 버튼을 만들어 넣으면 된다.
<li key={idx}>{item}<button onClick={delBtn}>❌</button></li>
- 버튼을 클릭하면 delBtn 함수가 실행된다. 이 함수는 todos 배열중에 하나를 삭제 하는 것인데 어떤 값인지를 특정해야만 한다. 그래서 현재 클릭한 todos의 값의 index 번호를 넘겨줄 필요가 있다. 그래서 className로 인덱스 번호를 넘겨 줄 것이다.
<button className={idx} onClick={delBtn}>❌</button>
- 이제 delBtn()함수를 만든다. 먼저 인덱스 값을 변수에 담는다.
const idx = e.target.className;
그리고 이 idx와 todos의 각 배열의 값과 비교해서 같은 값이면 그 값은 제외하고 새로운 배열을 만드는 filter함수를 사용할 것이다.todos.filter((item,todoIdx)=>parseInt(idx) !== todoIdx)
- parseInt()를 사용한 이유는 className의 타입은 string이고 todoidx는 number이기 때문이다. 이제 마지막으로 이렇게 filter로 걸러서 만들어진 새로운 배열을 setTodos()를 이용해서 변경 시켜주면 된다.
이제 모두 끝났다. 아래는 위의 설명에 대한 예제 코드이다. 이 과정은 노마드코더님의 무료 강좌 과정을 참고해서 만들었다.
todo list 코드
import {useState, useEffect} from 'react'; function App() { const [todo, setTodo] = useState(); const [todos, setTodos] = useState([]); const onChange = (e)=> setTodo(e.target.value); const deleteBtn = (e) => { const idx = e.target.className setTodos(todos.filter((item, todoIndex) => { return parseInt(idx) !== todoIndex }) ); }; const onSubmit = (e)=> { e.preventDefault(); if(todo===""){ return; } setTodo("") setTodos(currentArray => [...currentArray, todo]) } return ( <div> <h1>My Todos ({todos.length}) </h1> <form onSubmit={onSubmit}> <input onChange={onChange} value={todo || ''} type="text" placeholder='Write To Do List' /> <button>Add To Do</button> </form> <hr/> <ul> {todos.map((item,idx)=>{ return <li key={idx}>{item}<button className={idx} onClick={deleteBtn}>❌</button></li> })} </ul> </div> ); } export default App;