-
[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}/>
<Forminput1={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 ? (<inputtype="text"value={editedTitle}onChange={handleChange}/>) : (<span>{data.title}</span>)}<buttonstyle={btnStyle}onClick={() => deleteData(data.id)}>x</button>{editingId === data.id ? (<><buttonstyle={btnStyle}onClick={() => saveEditing(data.id)}>저장</button><buttonstyle={btnStyle}onClick={cancelEditing}>취소</button></>) : (<buttonstyle={btnStyle}onClick={() =>startEditing(data.id, data.title)}>수정</button>)}</p></div>))}</div>);}이 List.js 코드에서
<><buttonstyle={btnStyle}onClick={() => saveEditing(data.id)}>저장</button><buttonstyle={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}><inputtype="text"name="input1"style={{ padding: "8px" }}value={input1}onChange={handleChange}/><inputtype="text"name="input2"style={{ padding: "8px" }}value={input2}onChange={handleChange}/><inputtype="submit"value="생성하기"className="btn"style={{ flex: "1" }}/></form></div>);}이렇게 리액트로 투두앱 만들기 성공!
(그나저나 gpt에게 도움을 받으면 과연 그게 내 코드라고 볼 수 있는지 모르겠다... 보면 이해는 되는데 그 부분을 다시 혼자 백지상태에서 해보라고 하면 못할 것 같은 느낌... 제발 천천히좀 발전해라)
'React' 카테고리의 다른 글
모던 리액트 Deep dive - 클래스, 클로져 (3) 2024.02.18 모던 리액트 Deep Dive - 리액트 개발을 위해 꼭 알아야 할 JS (1) 2024.02.12 Funnel에서의 상태관리 고민 (0) 2024.01.30 왕초보가 작성한 토스 퍼널의 아주 기초적인 사용법 (0) 2024.01.19 리액트에서 .env 사용하기 (카카오 로그인) (0) 2023.11.06