React

[React] to do app 만들기

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