ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React] to do app 만들기
    React 2023. 7. 11. 19:27

    가장 기초적이라 할 수 있는 to do app을 만들어보자. 

     

    만들면서 해멨던 부분을 위주로 기록해보겠다.

     

    우선적으로 App.js 전체 코드부터 살펴보자.

     

    import React, { useEffect, useState } from "react";
    import List from "./components/List";
    import Form from "./components/Form";

    const initialTodoData = localStorage.getItem("todoData")
    ? JSON.parse(localStorage.getItem("todoData"))
    : [];

    export default function App() {
    const [todoData, setTodoData] = useState(initialTodoData);
    const [input1, setInput1] = useState("");
    const [input2, setInput2] = useState("");

    const handleSubmit = (e) => {
    e.preventDefault();

    let newTodo = {
    id: Date.now(),
    title: `${input1} ${input2}`,
    };

    setTodoData((prev) => [...prev, newTodo]);
     
    setInput1("");
    setInput2("");
    };

    const removeAll = () => {
    setTodoData([]);
    }

    useEffect(() => {
    localStorage.setItem("todoData", JSON.stringify(todoData));
    }, [todoData]);

    return (
    <div>
    <div>
    <h3>Create</h3>
    <button onClick={removeAll}>전체 삭제</button>
    </div>

    <List todoData={todoData}
    setTodoData={setTodoData}
    />
     

    <Form
    input1={input1}
    input2={input2}
    setInput1={setInput1}
    setInput2={setInput2}
    handleSubmit={handleSubmit}
     
    />
    </div>
    );
    }

     

    localStorage를 이용하기 위해 코드 작성.

    분명히 잘한 것 같은데 자꾸 오류 뜨길래 1차 당황.

    아무리 봐도 모르겠어서 gpt에게 질문하니,

    initialTodoData를 먼저 선언을 하지 않으니 오류가 발생하는 거라고 하더라. 그래서 사진처럼 저 코드를 맨 위로 올렸더니 해결!

     

    export default function App() {
    const [todoData, setTodoData] = useState(initialTodoData);
    const [input1, setInput1] = useState("");
    const [input2, setInput2] = useState("");

    input창을 두 개를 따로 설정했는데, 내가 봤을 땐 이거 분명히 하나로 묶어서 진행하는 방식이 있을 것 같다.

    내일은 하나로 합쳐서 해봐야지.

     

    useEffect(() => {
    localStorage.setItem("todoData", JSON.stringify(todoData));
    }, [todoData]);

    useEffect도 오늘 처음 알았음 ㅋ

    굉장히 신기했다. 뒤 배열이 바뀔 때만 렌더링된다는게  ㅋㅋㅋ

     

     

    다음은 수정하는 기능을 만들어보자

     

    //수정하기

     

    import React, { useState, useEffect } from 'react';

    export default function List({
    todoData,
    setTodoData,
    }) {
    const [editingId, setEditingId] = useState(null);
    const [editedTitle, setEditedTitle] = useState('');

     

    useState(null)은 gpt의 도움을 좀 받았다. 투두앱에서는 수정하는 기능이 가장 어려웠던듯.

     

    그렇게 해서 List.js  전체 코드는

     

    import React, { useState, useEffect } from 'react';

    export default function List({
    todoData,
    setTodoData,
    }) {
    const [editingId, setEditingId] = useState(null);
    const [editedTitle, setEditedTitle] = useState('');

    const btnStyle = {
    border: 'none',
    padding: '5px',
    };

    const deleteData = (id) => {
    let newTodoData = todoData.filter((data) => data.id !== id);
    setTodoData(newTodoData);
     
    };

    const startEditing = (id, title) => {
    setEditingId(id);
    setEditedTitle(title);
    };

    const cancelEditing = () => {
    setEditingId(null);
    setEditedTitle('');
    };

    const saveEditing = (id) => {
    const updatedTodoData = todoData.map((data) => {
    if (data.id === id) {
    return {
    ...data,
    title: editedTitle,
    };
    }
    return data;
    });

    setTodoData(updatedTodoData);
    setEditingId(null);
    setEditedTitle('');
    localStorage.setItem('todoData', JSON.stringify(updatedTodoData));
    };

    const handleChange = (e) => {
    setEditedTitle(e.target.value);
    };



    return (
    <div>
    {todoData.map((data) => (
    <div key={data.id}>
    <p>
    {editingId === data.id ? (
    <input
    type="text"
    value={editedTitle}
    onChange={handleChange}
    />
    ) : (
    <span>{data.title}</span>
    )}
    <button
    style={btnStyle}
    onClick={() => deleteData(data.id)}
    >
    x
    </button>
    {editingId === data.id ? (
    <>
    <button
    style={btnStyle}
    onClick={() => saveEditing(data.id)}
    >
    저장
    </button>
    <button
    style={btnStyle}
    onClick={cancelEditing}
    >
    취소
    </button>
    </>
    ) : (
    <button
    style={btnStyle}
    onClick={() =>
    startEditing(data.id, data.title)
    }
    >
    수정
    </button>
    )}
    </p>
    </div>
    ))}
    </div>
    );
    }

    이 List.js 코드에서

    <>
    <button
    style={btnStyle}
    onClick={() => saveEditing(data.id)}
    >
    저장
    </button>
    <button
    style={btnStyle}
    onClick={cancelEditing}
    >
    취소
    </button>
    </>

    여기서 이 부분 전체를 <div></div>로 묶는 것 보다 그냥 <> </>로 묶는게 더 센스 있다는 것도 알게 되었다.

     

    마지막으로 Form.js 전체 코드를 보자

    import React, { useState } from "react";

    export default function Form({
    input1,
    input2,
    setInput1,
    setInput2,
    handleSubmit,
    }) {
    const handleChange = (e) => {
    if (e.target.name === "input1") {
    setInput1(e.target.value);
    } else if (e.target.name === "input2") {
    setInput2(e.target.value);
    }
    };

    return (
    <div>
    <form style={{ display: "flex" }} onSubmit={handleSubmit}>
    <input
    type="text"
    name="input1"
    style={{ padding: "8px" }}
    value={input1}
    onChange={handleChange}
    />
    <input
    type="text"
    name="input2"
    style={{ padding: "8px" }}
    value={input2}
    onChange={handleChange}
    />
    <input
    type="submit"
    value="생성하기"
    className="btn"
    style={{ flex: "1" }}
    />
    </form>
    </div>
    );
    }

    이렇게 리액트로 투두앱 만들기 성공!

     

    (그나저나 gpt에게 도움을 받으면 과연 그게 내 코드라고 볼 수 있는지 모르겠다... 보면 이해는 되는데 그 부분을 다시 혼자 백지상태에서 해보라고 하면 못할 것 같은 느낌... 제발 천천히좀 발전해라)

Designed by Tistory.