초보자를 위한 반응

안녕하세요 오늘은 반응의 기본 원리를 이해할 수 있는 반응형 할일 목록 앱을 만들 것입니다.

여기에서 코드 샌드박스CodeSandbox를 사용하여 웹 앱을 더 빠르게 빌드할 수 있는 템플릿을 제공하는 반응을 시작할 수 있습니다.

할 일 앱으로 시작하려면 반응 템플릿을 선택하여 새 샌드박스를 만듭니다.


샌드박스 반응 템플릿을 생성한 후 반응에서 파일이 어떻게 구성되는지 확인하고 이 구조는 반응에서 일반적입니다.

앱.js




import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}



할 일 목록 애플리케이션의 경우 모든 코드는 app.js에서 수행해야 합니다.

이제 시작하겠습니다...



1) 앱에 입력 요소 추가



앱.js




import "./styles.css";

export default function App() {
  return (
    <div className="App">
       // heading
        <div className="heading">
          <h1>TO-DO App</h1>
       </div>


      // form element to take input from user

        <form className="formtodo">
          <input placeholder="Enter Your Text Here..."
            type="text"
            id="todoValue"
          ></input>
          <button type="submit">Add Todo</button>
        </form>


    </div>
  );
}



2) onChange 및 onSubmit을 입력에 추가



앱.js




import "./styles.css";

export default function App() {

function handleSubmit(){
// event handler function
}

function changeHandler(e){
// event handler function
}

return (
    <div className="App">
       // heading
        <div className="heading">
          <h1>TO-DO App</h1>
       </div>


      // form element to take input from user
      // adding onSubmit and onChange event listener.

        <form className="formtodo" onSubmit={handleSubmit}>
          <input 
            onChange={changeHandler}
            placeholder="Enter Your Text Here..."
            type="text"
            id="todoValue"
          ></input>
          <button type="submit">Add Todo</button>
        </form>


    </div>
  );
}



여기에서 사용자 입력을 처리하기 위해 두 개의 이벤트 리스너 메서드 onChange 및 onSubmit을 선언했으며 이러한 이벤트 리스너 메서드는 사용자 입력을 추가로 처리하기 위해 이벤트 핸들러 함수를 호출합니다.

3) useState 후크 추가



후크 란 무엇입니까? 후크는 상태 변수를 추가하고 업데이트할 수 있는 특수 기능입니다. 따라서 여기서는 useState 후크를 사용하여 작업 목록을 저장하고 업데이트할 것입니다.

앱.js




import "./styles.css";
import {useState} from 'react';

export default function App() {
const [todoValue, setTodoValue] = useState('');
const [todos, settodos] = useState([]);

function handleSubmit(event){
// event handler function
event.preventDefault(); // this will prevent default behaviour of form on submit
}

function changeHandler(event){
// event handler function
setTodoValue(event.target.value);
}

return (
    <div className="App">
       // heading
        <div className="heading">
          <h1>TO-DO App</h1>
       </div>


      // form element to take input from user
      // adding onSubmit and onChange event listener.

        <form className="formtodo" onSubmit={handleSubmit}>
          <input 
            onChange={changeHandler}
            placeholder="Enter Your Text Here..."
            type="text"
            id="todoValue"
          ></input>
          <button type="submit">Add Todo</button>
        </form>


    </div>
  );
}



(event.target.value) 현재 입력 값을 가져오고 해당 현재 입력 값을 changeHandler 함수의 상태 변수(setTodoValue)에 할당합니다.

4) 작업 추가



앱.js




import "./styles.css";
import {useState} from 'react';

export default function App() {
const [todoValue, setTodoValue] = useState('');
const [todos, settodos] = useState([]);

function handleSubmit(event){
// event handler function
event.preventDefault(); // this will prevent default behaviour of form on submit

if (todoValue === undefined ||
    todoValue === "" ||
    todoValue?.trim() === ""){
      alert("You are lazy!!! enter proper value.");
    }else {
        const todo = {
        value: todoValue,
        done: false
      };

      // spreading of previous value of todos
      settodos([...todos, todo]);
      document.getElementById("todoValue").value = "";
      // console.log(todoValue);
      settodoValue("");
      // console.log(todoValue)
    }


}

function changeHandler(event){
// event handler function
setTodoValue(event.target.value);
}

return (
    <div className="App">
       // heading
        <div className="heading">
          <h1>TO-DO App</h1>
       </div>


      // form element to take input from user
      // adding onSubmit and onChange event listener.

        <form className="formtodo" onSubmit={handleSubmit}>
          <input 
            onChange={changeHandler}
            placeholder="Enter Your Text Here..."
            type="text"
            id="todoValue"
          ></input>
          <button type="submit">Add Todo</button>
        </form>

       <div className="output">
        {todos &&
          todos.map((task, i) => {
            return (
              <div className="todo-list" key={task.value} id={i}>
                <button>
                  {task.value}
                </button>              
              </div>
            );
          })}
      </div>

   </div>
  );
}



우리는 (event.target.value)에 의해 입력 값을 취하고 그 값을 상태 변수(setTodoValue(e.target.value))에 할당합니다. 작업 제출 시 handleSubmit 함수가 호출되고 그렇지 않은 경우 빈 값을 확인합니다. handleSubmit 함수의 else 블록에 키(값, 완료)의 객체를 만들고 배열 메서드의 settodos([...todos,todo])확산을 사용하여 상태 배열에 추가합니다.

작업 목록을 표시하기 위해 todo 배열의 매핑이 완료되었습니다.
line-through 및 delete와 같은 다른 작업의 경우 todos 배열을 통해 매핑하는 동안 인덱스 {i}에 액세스해야 합니다.

5) 태스크를 삭제하고 라인 스루



앱.js




import "./styles.css";
import { useState } from "react";
export default function App() {
  const [todoValue, settodoValue] = useState("");

  const [todos, settodos] = useState([]);

  const handleDone = (e) => {
    const { id } = e.target.parentElement;
    todos[id].done = !todos[id].done;
    // console.log(todos[id].done, todos[id].value);
    settodos([...todos]);
  };

  function handleSubmit(e) {
    e.preventDefault();

    if (
      // todoValue === <strong>[&rlm;&rlm;&lrm;]</strong> ||
      // todoValue?.trim() == " ‏‏‎ " ||

      todoValue === undefined ||
      todoValue === "" ||
      todoValue?.trim() === ""
    ) {
      alert("You are lazy!!! enter proper value.");
    } else {
      const todo = {
        value: todoValue,
        done: false
      };
      // spreading of previous value of todos
      settodos([...todos, todo]);
      document.getElementById("todoValue").value = "";
      // console.log(todoValue);
      settodoValue("");
      // console.log(todoValue)
    }
  }

  function hanleDelete(e) {
    const { id } = e.target.parentElement;
    console.log(id);
    console.log(e.target.parentElement);
    todos.splice(id, 1);
    settodos([...todos]);
  }

  function changeHandler(event) {
    settodoValue(event.target.value);
    // console.log(event.target.value);
  }

  return (
    <div className="App">
      <div className="heading">
        <h1>TO-DO App</h1>
      </div>

      <div>
        <form className="formtodo" onSubmit={handleSubmit}>
          <input
            placeholder="Enter Your Text Here..."
            type="text"
            id="todoValue"
            onChange={changeHandler}
          ></input>

          <button type="submit">Add Todo</button>
        </form>
      </div>

      <div>
        {todos &&
          todos.map((task, i) => {
            return (
              <div className="todo-list" key={task.value} id={i}>
                <button
                  // if task.done is true then apply "done"  to classname else apply "not-done".. task.done will be changed to true on click over it

                  className={task.done ? "done" : "not-done"}
                  onClick={handleDone}
                >
                  {task.value}
                </button>
                {/* {task.value} */}
                <button onClick={hanleDelete}>Delete</button>
              </div>
            );
          })}
      </div>
    </div>
  );
}



클릭 버튼에 대한 삭제 작업의 경우 핸들 삭제를 호출하고 이 이벤트 핸들러 함수는 작업 ID를 가져오고 splice 메서드를 사용하여 배열에서 클릭된 {id} Task를 제거하고 splice 메서드 이후에 todos 배열을 업데이트합니다.

클릭 버튼에 대한 라인 스루 작업의 경우 handleDone을 ​​호출하고 해당 기능에서 키 "done:false"를 반대 값인 "done:true"로 토글하고 "done:true"변경 값을 settodos([. ..todos]).이 작업을 위해 조건부 className을 정의하고 CSS line-through 속성을 사용했습니다.

스타일.css




@import url("https://fonts.googleapis.com/css?family=Roboto+Condensed:300i,400,400i,700");

* {
  padding: 0;
  margin: 0;
}

.heading {
  color: #332d36;
  font-weight: 300;
  font-size: 2.5rem;
  text-align: center;
}
body {
  background: skyblue;
}

.App {
  font-family: sans-serif;
  text-align: center;
  /* background: skyblue; */
  padding: 1rem;

  font-family: "Roboto Condensed", sans-serif;
}

button,
input {
  all: unset;
  color: blue;
  -webkit-text-fill-color: blue;
  cursor: pointer;
}

.done {
  text-decoration: line-through;
}

input {
  padding: 1rem;
  border-radius: 5px;
  text-align: left;
  cursor: text;
  background: whitesmoke;
  /* outline-width: 0.1rem; */
  box-shadow: 1px 2px 5px 1px;
}

[type="submit"] {
  padding: 1rem;
  margin-left: 0.5rem;
  background: whitesmoke;
  border-radius: 10px;

  box-shadow: 1px 4px 1px 1px;
}

[type="submit"]:active {
  box-shadow: 1px 2px 1px 1px;
}
.todo-list {
  background: wheat;
  padding: 1rem;
  margin: 1rem auto;
  border-radius: 10px;
  max-width: 500px;
  width: 100%;
  /* overflow: scroll; */
  display: grid;
  grid-template-columns: 4fr 1fr;
}

.formtodo {
  /* background: whitesmoke; */
  padding: 1rem;
  margin: 1rem auto;
  max-width: 550px;
  display: grid;
  grid-template-columns: 4fr 1fr;
}

.not-done,
.done {
  border-radius: 10px 0 0 10px;
  border: none;
  text-align: left;
  padding: 1rem;
}



이것으로 할 일 목록 앱이 완성되었으며 참조용으로 내 codesandbox 링크를 공유합니다.

좋은 웹페이지 즐겨찾기