개발자라면 지나칠 수 없지, 그건 바로 'todo list' 만들기 - 별도 서버 필요없는거 알고 있었나요?

const job = '프론트엔드';·2023년 8월 10일
0
post-thumbnail

today is..

🖥 완성화면 부터 보고 오실게효 !

직접보러가기-배포화면
전체코드 보러가기-git

📌 'React & styled-components'로 todo list 만들기 !

⭐ CRUD ⭐로 기능 설명하기

✅ 기능 1. Creat(생성) form에서 submit하기

status1 form에서 입력
1-1. form 태그 필요(submit으로 입력 정보를 넘겨 받아야 하기 때문)
1-2. todo내용인 text를 입력한 input창 필요
1-3. 내용을 submit으로 넘길 버튼 역할을 할 input창이 필요


status2 입력 text를 받아서 submit으로 넘김
2-1. text input에 입력(todo[]에 들어갈 내용 입력)
2-2. 추가버튼을 누름(submit 형식)


status3 배열형식의 todo[]에 저장
3-1. todo[]에 최신 상태로 입력한 내용을 계속해서 const todo=["할일1", "할일2",...,"최신추가"]로 추가됨

코드로 확인하기

// todo리스트의 상태를 관리할 useState필요
const [todo, setTodo] = useState([]);

useState의 상태관리 원리

  • todo는 현재 상태, setTodo는 최신 상태
  • setTodo의 상태가 바로 todo인 현재상태가 됨
  • todo가 눈에 보여지고 있음, 뒤에서 setTodo가 업데이트 되고 있음, 업데이트가 완료되면 기존 todo 처럼 눈에 보여짐
  • useState([])는 초기 값이 빈배열이라는 것
    (예시의 초기화면에는 아무것도 입력하지 않았기 때문에 todo리스트 화면이 비어있음)
	  <form
        onSubmit={(e) => {
          e.preventDefault();    
          handleSubmit(e.target.todo.value);
          e.target.todo.value = "";
        }}
      >
        <input
          type="text"
          placeholder="Add a todo"
          name="todo"
          autocomplete="off"
        />
        <input type="submit" value="+" />
      </form>

form submit으로 작성한 내용을 넘겨주기 위함
onSubmit 이벤트 핸들러를 사용

  • onSubmit은 폼이 제출되면 콜백함수가 실행
  • e.preventDefault();은 submit될 때 새로고침(렌더)을 방지하기 위한 코드
  • handleSubmit함수에 e.target.todo.value를 담아서 넘김
  • 그리고 e.target.todo.value에 빈값을 넣음
    여기서 e.target.todo.value는?
  • 'e'는 발생한 이벤트에 대한 정보가 포함된 객체
  • text 작성 input의 name값에 todo를 줬으며, 해당 input창에 입력 값이 value가 됨
  • 따라서 onSubmit이 발생하면 1) 렌더를 막고, 2) 작성된 value값을 handleSubmit함수에 담아서 보내고, 3) input 입력창을 비워냄
 const handleSubmit = (todoText) => {
    setTodo([
      ...todo,
      {
        todoText: todoText,
        todoId: todoId,
        todoDone: false,
      },
    ]);
    setTodoId(todoId + 1);
  };

handleSubmit이 하는 일: 입력값을 todoText로 받아와서, todoText를 이용해 객체를 생성해서 저장

  • 받아온 todo.value는 todoText로 받아옴
  • 업데이트 될 setTodo안에는 ...todo(기존 배열에 저장된 내용) + 새로 추가될 내용(todoText: 추가된 할 일 내용, todoId: 식별하기 위한 숫자, todoDone: 완료상태를 보여줌)을 객체 형태로 업데이트 됨
//고유한 식별자를 지정하기 위한 todoId로 상태관리
  const [todoId, setTodoId] = useState(0);
  • 따라서, handleSubmit에서 setTodo로 상태가 없데이트 되면, todoId도 +1로 상태를 업데이트 시켜서 구분

✅ 기능 2. Read(읽기) submit한 내용 보여주기

list형식으로 배열에 저장된 내용들이 출력됨

 	 <ul>
        {todo.map((item, index) => {
          return (
            <li key={index}>
              <span>
                {item.todoText}
              </span>

             ...생략...
             
            </li>
          );
        })}
      </ul>
  • 작성해서 받아온 내용을 map으로 뿌려줌(Read)
    map의 기능
배열이름.map((item, index) => {
  return 반환
  
})
  • 배열의 속성을 순서대로 순환하면서 배열 하나씩 retrun값으로 반환(반복)
  • todo[]에 기존에 있는 리스트와 새로 추가된 내용들이 return을 통해 보여짐

✅ 기능 3. Update(수정) 보여진 내용(할 일) 완료 표시

list항목을 누르면 할 일 완료처리 가능

			 <span
                onClick={() => {
                  handleToggle(item.todoId);
                }}>
                {item.todoText}
              </span>
  • onClick 이벤트 핸들러를 이용
  • span 태그 내에 있는 나열된 todo text의 이벤트를 적용
  • handleToggle()는 todoId를 통해서 식별하고 있음
const handleToggle = (todoId) => {
    setTodo(
      todo.map((item, index) => {
        return item.todoId === todoId
          ? { ...item, todoDone: !item.todoDone }
          : item;
      })
    );
  };
  • 전달받은 todoId에 해당하는 내용을 누르면, map을 통해 setTodo 상태를 업데이트 시킴
  • map은 todo배열을 순환 item.todoId가 전달받은 todoId와 같으면 todoDone이 false면 true로 true면 false로 바꾸고, 같지 않으면 그냥 두는 상태를 반환

✅ 기능 4. Delete(삭제) 보여진 내용 삭제하기

button을 누르면 todo[]에 해당 요소가 삭제

 	<button
       onClick={() => {
          handleDelete(item.todoId); }} >
                del
    </button>

삭제 버튼을 생성

  • onClick 이벤트 핸들러를 통해 버튼을 누르면 콜백함수가 실행됨
  • 콜백함수내에 handleDelete함수
  const handleDelete = (todoId) => {
    setTodo(
      todo.filter((item) => {
        return item.todoId !== todoId;
      })
    );
  };
  • todoId를 인수로 전달받고, 콜백함수를 실행
  • filter를 통해 콜백함수가 true를 반환하는 요소만 남겨진 배열을 반환받음
  • 따라서 전달받은 todoId와 같지 않으면 true를 반환
    (= 같지 않다는 건 삭제하기 위해 선택받은 todoId가 아니라는 것)
  • todoId와 일치해서 false로 삭제된 항목을 제외하고 배열로 다시 반환(삭제되지 않은 항목만 반환)

📌 로컬스토리지(local storage)에 작성한 내용을 저장

로컬 스토리지?

  • 웹 브라우저에는 로컬스토리지라는 속성이 있음
  • 현재 도메인의 로컬 저장소에 접근할 수 있게 해줌
  • 로컬 저장소는 웹브라우저에서 각 도메인에 대해 할당해주는 저장 공간으로 여기에는 데이터를 영구적으로 보관할 수 있음
  • window.localStorage 형태

개발자도구 - Application- Storage Local Storage 에서 확인가능

  • 항목을 추가하면 객체 형태로 배열로 저장되는 것을 확인할 수 있음

useEffect로 로컬스토리지 저장하기

  useEffect(() => {
    localStorage.setItem("todo", JSON.stringify(todo));
  }, [todo]);
  • useEffect는 두가지 인자를 받으며, 첫번째 인자는 콜백함수, 두번째 인자는 의존성 배열에 해당함
  • 의존성 배열에 있음, 배열 내부의 내용이 업데이트 될 때마다 콜백함수를 실행
  • 의존성 배열이 비어있음, 최초 렌더시 한번만 콜백함수를 실행
  • 의존성 배열이 아예 없음, 매번 콜백함수 실행
  • 위 코드에는 의존성 배열 안에 todo가 있기 때문에, todo가 갱신될 때마다 콜백함수를 실행시킴
  • 콜백함수의 내용은 localStorage.setItem = 키와 밸류를 전달받아서 저장하는 기능으로 key:"todo", value: json 문자 형태로 변환(JSON.stringify)해서 저장

useEffect로 컴포넌트가 만들어지는 순간에 로컬스토리지 읽어들이기

  useEffect(() => {
    const defaultTodo = JSON.parse(localStorage.getItem("todo"));

    if (!defaultTodo) return;
    setTodo(defaultTodo);

    if (defaultTodo.length !== 0) {
      setTodoId(defaultTodo[defaultTodo.length - 1].todoId + 1);
    }
  }, []);
  • 의존성 배열이 비어있기 때문에 최초 1회만 콜백함수를 실행시킴
  • 콜백함수에는 JSON형으로 변환된 객체를 다시 자바스크립트 형식으로 변환(JSON.parse)
  • 전달받은 key에 해당하는 value를 반환하는 getItem을 통해 key: "todo"에 해당하는 value를 반환 받은 내용을 담은 defaultTodo변수를 생성
  • localStorage에서 "todo" 키로 저장된 데이터를 가져와서 처리하고, 필요한 상태를 업데이트

📌 CSS 적용

styled-components 컴포넌트를 모아둔 js 파일을 생성 (import/export)

hover 효과를 통해 동적인 느낌을 줌
transition으로 자연스러운 느낌을 줌

타이틀 부분

  • hover 했을때(마우스를 올렸을때) letter-spacing을 주고 자연스럽게 간격이 벌어지는 느낌을 주기 위해 transition효과를 줌
  • 또한, 마우스를 떼어 낼 때 hover효과가 바로 사라져서 어색한 효과를 줄이기 위해 transition효과를 동일하게 줌

submit(+)버튼 부분

  • hover 효과로 backround-color를 조절함으로써 마우스가 버튼에 올려져 있음을 표시함

todo list부분

  • background color를 투명으로 바꾸고, Read와 Delete를 적용하기 위해 항목을 구분하기 위해 hover시 background color를 다르게 함

결론: 왜 나는 useRef를 써야 한다고 생각했던가....


profile
`나는 ${job} 개발자`

0개의 댓글