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