useState, useEffect, prop을 사용하여 To Do List를 만들어 보자.
import { useState } from "react";
function App() {
const [toDo, setToDo] = useState("");
const onChange = (event) => setToDo(event.target.value);
//console.log(toDo);
return (
<div>
<input
onChange={onChange}
value={toDo}
type="text"
placeholder="Write your to do..."
></input>
</div>
);
}
export default App;
event.preventDefault();
import { useState } from "react";
function App() {
const [toDo, setToDo] = useState("");
const onChange = (event) => setToDo(event.target.value);
//form의 button 클릭시 submit 되는데 그 때 자동 새고 되는 거 막기 위해 아래 코드 작성
const onSubmit = (event) => {
event.preventDefault();
//console.log(toDo);
};
return (
<div>
<form onSubmit={onSubmit}>
<input
onChange={onChange}
value={toDo}
type="text"
placeholder="Write your to do..."
></input>
<button>Add To Do</button>
</form>
</div>
);
}
export default App;
if (toDo === "") {
return;
}
setToDo("");
import { useState } from "react";
function App() {
const [toDo, setToDo] = useState("");
const onChange = (event) => setToDo(event.target.value);
//console.log(toDo);
//form의 button 클릭시 submit 되는데 그 때 자동 새고 되는 거 막기 위해 아래 코드 작성
const onSubmit = (event) => {
event.preventDefault();
//console.log(toDo);
//toTo 비어 있으면 submit 되지 않도록 return 시키자.
if (toDo === "") {
return;
}
//그리고 submit되고 나서는 input 값 비워주자. 그러려면 모디파이어에 빈 값 주면 된다.
setToDo("");
};
return (
<div>
<form onSubmit={onSubmit}>
<input
onChange={onChange}
value={toDo}
type="text"
placeholder="Write your to do..."
></input>
<button>Add To Do</button>
</form>
</div>
);
}
export default App;
import { useState } from "react";
function App() {
//1. input value 값으로 toDo 받아오기
const [toDo, setToDo] = useState("");
//2. 여러개의 toDo 담는 array, 디폴트 값은 비어 있는 array로 작성
const [toDos, setToDos] = useState([]);
//toDo를 추가할 때 이 array에 추가해 주기
const onChange = (event) => setToDo(event.target.value);
//form의 button 클릭시 submit 되는데 그 때 자동 새고 되는 거 막기 위해 아래 코드 작성
const onSubmit = (event) => {
event.preventDefault();
//toTo 비어 있으면 submit 되지 않도록 return 시키자.
if (toDo === "") {
return;
}
//그리고 submit되고 나서는 input 값 비워주자. 그러려면 모디파이어에 빈 값 주면 된다.
setToDo("");
};
return (
<div>
<form onSubmit={onSubmit}>
<input
onChange={onChange}
value={toDo}
type="text"
placeholder="Write your to do..."
></input>
<button>Add To Do</button>
</form>
</div>
);
}
export default App;
📝 state를 수정하는 방법
- 바닐라 자바스크립트에서는 toDos가 array 이기 때문에
toDos.push()
를 사용하면 된다.- ❗️ 하지만 리액트에서는 state를 직접 수정하지 않는다는 것을 기억하자!
toDo =""
라고 작성하지 않고, 함수를 사용하여 state를 수정한다.- 따라서 toDo를 수정하든, toDos를 수정하든, state를 수정하고 싶다면 수정하는 함수, 즉 모디파이어를 사용해야 한다.
array를 직접 수정하지 않고 setToDos()로 array에 element 추가하는 방법
const food = [1,2,3,4];
//어떻게 새로운 어레이를 만들 수 있을까?
[5, food];
//라고 작성할 경우 [6, Array(4)]라고 뜬다.
//5에 food 어레이의 elements를 더해 새로운 어레이를 만들어야 한다.
//그러기 위해서는 아래와 같이 적으면 된다.
[5, ...food]
import { useState } from "react";
function App() {
//1. input value 값으로 toDo 받아오기
const [toDo, setToDo] = useState("");
//2. 여러개의 toDo 담는 array, 디폴트 값은 비어 있는 array로 작성
const [toDos, setToDos] = useState([]);
const onChange = (event) => setToDo(event.target.value);
//form의 button 클릭시 submit 되는데 그 때 자동 새고 되는 거 막기 위해 아래 코드 작성
const onSubmit = (event) => {
event.preventDefault();
//toTo 비어 있으면 submit 되지 않도록 return 시키자.
if (toDo === "") {
return;
}
//이전값 받아오기
// 첫 번째 인자로 현재 state 받아오는 함수 적어주자.
//그리고 새로운 array 받아와서 return해주자. 이 부분이 상당히 중요하다. state는 항상 새로운 거여야 한다.
//그리고 그 새로운 []에는 방금 적은 toDo와, 현재 toDos의 어레이의 엘리먼트를 넣어주면 된다. 이렇게 toDos가 방금 적은 toDo와 기존에 입력된 toDos의 엘리먼트가 합쳐진 새로운 어레이로 업뎃되게 해주자.
setToDos((currentArray) => [toDo, ...currentArray]);
//그리고 submit되고 나서는 input 값 비워주자. 그러려면 모디파이어에 빈 값 주면 된다.
setToDo("");
};
//적었던 값이 어레이에 잘 들어가고 있는지 확인해 보자.
console.log(toDos);
return (
<div>
<form onSubmit={onSubmit}>
<input
onChange={onChange}
value={toDo}
type="text"
placeholder="Write your to do..."
></input>
<button>Add To Do</button>
</form>
</div>
);
}
export default App;
<h1>My To Do List ({toDos.length})</h1>
jsx에 자바스크립트 넣고 싶으면
{}
중괄호 안에 넣으면 된다.
//모디파이어 setToDo로 비어 있는 String 값을 보내면, toDo는 빈 String 값으로 업데이트 된다.
setToDo("");
//🔥모디파이어로 단순히 값만 보내는 것이 아닌 함수를 보낼 수도 있다.
//함수를 보낼 때 react.js는 🔥함수의 첫 번째 argument로 현재 state를 보낸다.
//이는 현재 state를 계산하거나 새로운 state를 만드는데 사용할 수 있다.
setToDos((currentArray) => [toDo, ...currentArray]);
//즉 첫 번째 인자로 보낸 currentArray의 값은 === toDos 어레이인 것 ㅇㅇ!
//따라서 toDo와 toDos어레이 안의 element를 새로운 toDos 어레이로 return한다.(업데이트 한다.)
toDos Array 안에 있는 각각의 element를 component로 만들어 보자.
form 태그 밑에 <hr />
(horizontal rule) 작성하고 그 밑에 ul 태그를 작성한다.
ul 태그 안에 자바스크립트 사용할 수 있도록 {}
사용해 toDos 배열 가져오자.
//생략
return (
<div>
<h1>My To Do List ({toDos.length})</h1>
<form onSubmit={onSubmit}>
<input
onChange={onChange}
value={toDo}
type="text"
placeholder="Write your to do..."
></input>
<button>Add To Do</button>
</form>
<hr />
<ul>
{toDos}
</ul>
</div>
);
}
export default App;
map()
사용하기
["item1", "item2", "item3"].map(배열의 모든 item에 대해 실행되는 함수)
array.map(fn)
은 array에 있는 item을 내가 원하는 것으로 바꿔주는 역할을 한다.- 배열의 모든 item에 대해 실행되는 함수에서, 무엇을 return 하든 그 return한 값이 새로운 array에 들어간다.
- 따라서 array의 item이 3개라면, 그 함수가 3번 실행된다.
- 결국 그 함수로부터 내가 return한 값을 새로운 array에 넣어준다.
- 예시
그런데 이렇게 굳이 쓸게 있을까?
보다시피 기존의 ite으로 접근할 수가 없게되었넹..^^..
["rm", "jin", "suga"].map((item) => item.toUpperCase())
{toDos.map((toDo) => <li>{toDo}</li>)}
import { useState } from "react";
function App() {
const [toDo, setToDo] = useState("");
const [toDos, setToDos] = useState([]);
const onChange = (event) => setToDo(event.target.value);
const onSubmit = (event) => {
event.preventDefault();
if (toDo === "") {
return;
}
setToDos((currentArray) => [toDo, ...currentArray]);
setToDo("");
};
console.log(toDos);
return (
<div>
<h1>My To Do List ({toDos.length})</h1>
<form onSubmit={onSubmit}>
<input
onChange={onChange}
value={toDo}
type="text"
placeholder="Write your to do..."
></input>
<button>Add To Do</button>
</form>
<hr />
<ul>
{toDos.map((toDo) => <li>{toDo}</li>)}
</ul>
</div>
);
}
export default App;
오케이! 이렇게 되면 []
안에 각각의 아이템이 리스트 형태로 들어가 진 모양인거다.
<ul>
<li>{item}</li>
<li>{item}</li>
<li>{item}</li>
</ul>
뭐 이런 모양새라고 생각하면 되겠다.
잘되긴 하는데 콘솔에 경고가 뜬다.
경고: 같은 컴포넌트의 리스트를 render할 때는 key라는 prop을 넣어주라고 한다.
이는 기본적으로 리액트가 list에 있는 모든 item들을 인식하기 때문이다.
해결: li에 key를 prop으로 넣어주면 된다.
map()에서 함수의 인자 부분을 살펴보면 key 값으로 쓸만한 게 보인다.
{toDos.map((toDo, index) => (
<li key={index}>{toDo}</li>
))}
두 번째 argument로 index를 보내서 key값으로 사용하면 unique한 키값을 얻을 수 있다.
array를 가져와서 그 array의 item을 변경해서 li되게 하기.
이야... 데이터는 바꿔주면되고 ui는 자동으로 바뀐다....^~^ 자바스크립트에서 넘어오니 이렇게 멋진 세상이...!
[toDo, ...currentArray]
라고 적은 순서 바꿔서 [...currentArray, toDo]
라고 적으면 to do input에 적은 순서대로 나온다. ^^! 이렇게 간단한데서 차이가 나는구나...!
현재 로컬스토리지를 활용해 저장하는 것은 아니기 때문에 간단하게 하기 위해 부모 요소를 찾아서 없애주면 된다.
import { useState } from "react";
function App() {
//1. input value 값으로 toDo 받아오기
const [toDo, setToDo] = useState("");
//2. 여러개의 toDo 담는 array, 디폴트 값은 비어 있는 array로 작성
const [toDos, setToDos] = useState([]);
const onChange = (event) => setToDo(event.target.value);
//form의 button 클릭시 submit 되는데 그 때 자동 새고 되는 거 막기 위해 아래 코드 작성
const onSubmit = (event) => {
event.preventDefault();
//toTo 비어 있으면 submit 되지 않도록 return 시키자.
if (toDo === "") {
return;
}
//setToDos에 기존에 가지고 있던 currentArray의 element들과 toDo 넣어 return하기
setToDos((currentArray) => [...currentArray, toDo]);
//그리고 submit되고 나서는 input 값 비워주자. 모디파이어에 빈 값 주면된다.
setToDo("");
};
//투두리스트 삭제하기
const deleteToDo = (event) => {
//console.log(event.target.parentElement);
const li = event.target.parentElement;
li.remove();
};
return (
<div>
<h1>My To Do List ({toDos.length})</h1>
<form onSubmit={onSubmit}>
<input
onChange={onChange}
value={toDo}
type="text"
placeholder="Write your to do..."
></input>
<button>Add To Do</button>
</form>
<hr />
<ul>
{toDos.map((toDo, index) => (
<li key={index}>
{toDo}
<button onClick={deleteToDo}>❌</button>
</li>
))}
</ul>
</div>
);
}
export default App;
단순히 부모 요소를 삭제하는 것이 아닌 배열 안에 있는 index와 삭제할 index(버튼의 li)를 찾아서 삭제할 경우에는 filter함수를 사용하면 된다.
filter() 메서드는 주어진 함수의 테스트를 통과하는 모든 요소를 모아 새로운 배열로 반환한다.
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => word.length > 6);
console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]
<button onClick={() => deleteToDo(index)}>❌</button>
❌ 버튼을 누르면 deleteToDo()함수로 index를 보낸다.
deleteToDo()함수에 index값을 인자로 받아 온다.
const deleteToDo = (index) => {
setToDos(toDos.filter((toDo, toDoIndex) => index !== toDoIndex));
};
setToDos() 모디파이어
를 활용하여 toDos 배열에 필터링을 돌려 값을 반환받아 삭제된 것 같은 연출을 해주면 된다.toDos.filter((toDo, toDoIndex) => index !== toDoIndex)
!==
이렇게 하면 복잡하지만 index를 활용해 볼 수 있다는 점..^ㅇ^!
<button onClick={() => deleteToDo(index)}>❌</button>
() => deleteToDo(index)
이렇게 쓰는 이유는 "바로 실행"되지 않고 클릭을 기다리는 함수로 쓰기 위함이다. 왠지는 아직 잘 모르겠다.🥺🥲import { useState } from "react";
function App() {
//1. input value 값으로 toDo 받아오기
const [toDo, setToDo] = useState("");
//2. 여러개의 toDo 담는 array, 디폴트 값은 비어 있는 array로 작성
const [toDos, setToDos] = useState([]);
const onChange = (event) => setToDo(event.target.value);
//form의 button 클릭시 submit 되는데 그 때 자동 새고 되는 거 막기 위해 아래 코드 작성
const onSubmit = (event) => {
event.preventDefault();
//toTo 비어 있으면 submit 되지 않도록 return 시키자.
if (toDo === "") {
return;
}
//setToDos에 기존에 가지고 있던 currentArray의 element들과 toDo 넣어 return하기
setToDos((currentArray) => [...currentArray, toDo]);
//그리고 submit되고 나서는 input 값 비워주자. 모디파이어에 빈 값 주면된다.
setToDo("");
};
//투두리스트 삭제하기
const deleteToDo = (index) => {
setToDos(toDos.filter((toDo, toDoIndex) => index !== toDoIndex));
};
return (
<div>
<h1>My To Do List ({toDos.length})</h1>
<form onSubmit={onSubmit}>
<input
onChange={onChange}
value={toDo}
type="text"
placeholder="Write your to do..."
></input>
<button>Add To Do</button>
</form>
<hr />
<ul>
{toDos.map((toDo, index) => (
<li key={index}>
{toDo}
<button onClick={() => deleteToDo(index)}>❌</button>
</li>
))}
</ul>
</div>
);
}
export default App;
https://ko.reactjs.org/docs/lists-and-keys.html
리액트- 리스트와 키 관련 공식문서