ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Todo_List(feat. React)
    프로젝트/개인프로젝트 2023. 12. 6. 14:29
    728x90
    순수 js로 구현했던 todolist를 react로 한번 더 구현 해 보기로했다.
    react를 완전 찍먹 했던 경험이있어, 도전해봤는데 역시나 쉽지않았다.
    구글링과 gpt를 통해 어찌저찌 완성을 해봤다.

     


    🔎 완성

     

     

    기존과 기능면에서는 다른게없다. 배경색만 달라졌다

     


     

    🔎 구현 기능

    • input창에 입력 후 +버튼을 클릭하면 할일이 추가됨.
    • 삭제 버튼 클릭시 해당 목록 삭제
    • 할일 완료 클릭 시 해당 목록 줄 긋기
    • 입력창에 아무것도 입력안하고 +버튼 클릭시 alert창으로 경고창

     


    🔎  구현 방법

     

    App.js

     

    1. 뼈대부분

     <div className="Wrapper">
          <header className="tit">todo_List</header>
          <div className="content">
            <div className="input_f">
              <input
                id="todo_input"
                type="text"
                placeholder="내용을 입력하세요"
                value={inputValue}
                onChange={(e) => setInputValue(e.target.value)}
              ></input>
              <button id="add_btn" onClick={add}>
                <img src={plus}></img>
              </button>
            </div>
            <div className="result">
              {todos.map((todo, index) => (
                <div className="todolist" key={index}>
                  <span
                    onClick={() => toggleTodo(index)}
                    className={`todolist ${
                      todos[index].checked ? "completed" : ""
                    }`}
                  >
                    {todo.text}
                  </span>
                  <button className="delete_btn" onClick={() => delete_list(index)}>
                    X
                  </button>
                </div>
              ))}
            </div>
          </div>
        </div>

     

    1. 크게 제목과 컨텐츠가 들어갈 영역으로 나누어줬다.

    2. 컨텐츠가 들어갈 영역에 입력영역과 입력한 할일목록이 보여질 result영역으로 한번 더 나누어줬다.

    3. 입력칸에 value={InputValue}으로 설정해주고 onChange{(e) => setInputValue(e.target.value)}를 통해
       입력값의 최신값으로 value값을 업데이트 시켜준다.
    4. add_btn 은 onClick ={add(사용자 정의 함수)] 를 지정해, input창에 입력하고 add_btn 버튼을 클릭해했을 때
    add함수가 실행되어 할일 목록에 추가되도록 설정해준다.

     

    5.result 영역에 add버튼을 통해 할일 목록이 저장된 todos배열을 Map함수를 통해 출력시켜준다.

    6. map함수는 todo와 index를 매개변수를 갖고, 반복하여 todos의 할일목록 리스트를 출력시켜준다.

    7.span 태그를 클릭 시 toggleTodo(index) 함수에 index를 매개변수로 보내, 함수를 실행시켜,
      checked 상태에 따라 className을 변경시켜, 스타일을 다르게 적용하도록 해준다.

    8. delete_btn 클릭시 delete_list(index)함수를 실행시켜주며, index를 매개변수로 보내, 해당 항목만 삭제되도록
    하는 함수를 실행시키도록 한다.


    2. 함수부분

    const inputRef = useRef(null);
      const [inputValue, setInputValue] = useState("");
      const [todos, setTodos] = useState([]);
      function add() {
        if (inputValue === "") {
          alert("내용을 입력하세요");
        } else {
          setTodos([...todos, { text: inputValue, checked: false }]);
          setInputValue("");
          inputRef.current.focus();
        }
      }
    
      function delete_list(index) {
        const newTodos = [...todos];
        newTodos.splice(index, 1);
        setTodos(newTodos);
      }
    
      const toggleTodo = (index) => {
        const newTodos = [...todos];
        newTodos[index] = {
          ...newTodos[index],
          checked: !newTodos[index].checked,
        };
        setTodos(newTodos);
      };

     

    1. const[inputValue, setInputValue] = useState("");

       입력창에 입력되는 값을 관리해준다.

    2. const[todos,setTodos] = useState([]);

       입력된 항목들의 전체목록이 저장되기때문에 배열로 선언해줬다.

    3. function add

      입력된 할일 항목(InputValue)을 할일 목록(todos배열)에 추가시키는 함수이다.

      입력값이 없는 상태에서 add버튼을 클릭하면, alert를 통해 경고창이 나타나고,
      입력값을 입력 후 add 버튼을 클릭하면, else문이 실행되어 text:입력값 , checked:false 로 저장된다.

      이때 ...todos를 하는이유는, 이전에 입력된 값들을 나열하고, 뒤에 새로운 값을 입력하기 위해서다.

      ...을 생략하고 작성한다면, 그 이전 데이터들에 덮어씌워지기 때문이다.

    마지막으로, setInputValue("")를 통해, InputValue를 초기화 시켜주고
    inptRef.current.focus(); 함수를 통해 자동 포커스 되도록 설정해준다.

     

    4.function delete_list(index)

      delete_btn을 클릭하게되면 해당 index를 매개변수로 받아오게된다.

      const newTodos = [...todos]; 

      현재 할일목록들을 newTodos변수에 복제한다.

     

      newTodos.splice(index,1)
     자바스크립트의 메서드인 splice를 통해 해당 index위치에 요소를 삭제시킬수 있다.
    splice(start위치, 삭제할 갯수, 추가할요소들..)
    여기선 시작위치 Index와 삭제할 갯수 만 입력했기때문에,

    delete_btn을 통해 받아온 해당 항목의 index게시물만 삭제하여

    setTodos(newTodos); 

    할일목록을 업데이트 시켜준다.

     

    5. const toggleTodo = (index) =>{}
      const newTodos = [...todos];

      newTodos함수에 할일목록들이 저장된 todos 배열을 복제한다.

     

    newTodos[index]={
      ...newTodos[index], checked: !newTodos[index].checked,};

     

    복제된 newTodos배열에 매개변수로 받아온 index에 해당하는 선택된 할일목록을 가져와서

    checked 속성을 ! 를 통해 false 면 true로 true면 false로 상태를 변경시켜준다.

     

    setTodos(newTodos);를 통해 변경된 값을 업데이트 해준다.


    CSS

    * {
      padding: 0px;
      margin: 0px;
      box-sizing: border-box;
    }
    body {
      background-color: pink;
    }
    
    .Wrapper {
      .tit {
        text-align: center;
        margin-top: 20px;
        font-size: 30px;
        font-family: "Lucida Sans", "Lucida Sans Regular", "Lucida Grande",
          "Lucida Sans Unicode", Geneva, Verdana, sans-serif;
        font-weight: bold;
        color: beige;
      }
      .input_f {
        margin-top: 20px;
        display: flex;
        align-items: center;
        justify-content: center;
        #todo_input {
          width: 300px;
          height: 40px;
          outline: none;
        }
        #add_btn {
          width: 40px;
          height: 40px;
          border: none;
          background-color: pink;
          cursor: pointer;
          > img {
            width: 40px;
            height: 40px;
          }
        }
      }
      .result {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        .todolist {
          background-color: beige;
          width: 335px;
          margin-top: 15px;
          text-align: center;
          .delete_btn {
            border: none;
            margin-left: 10px;
            cursor: pointer;
            background-color: beige;
          }
        }
        .completed {
          text-decoration: line-through;
          color: gray;
        }
      }
    }
    
    ::placeholder {
      padding: 5px;
    }

     


    🔎 결론

     

    아무래도 기본 js를 사용하여 작성했던 todo_list때와 달리 리엑트는 익숙하지않아, 어려웠지만, 재밌었다.
    함수를 통해 매개변수를 받고 useState를 사용하여 값을 업데이트하는 방법들을
    좀 더 숙지해야될거같고, 나아가 redux같은 상태관리 라이브러리를 활용하는 방법도
    적용하는 방향으로 진행해보면 더 좋을 것 같다.

     

     

    💁🏻전체코드

    728x90

    댓글

Designed by Tistory.