[react] 배열에 항목 추가 / 배열에 항목 제거
https://react.vlpt.us/basic/13-array-insert.html
13. 배열에 항목 추가하기 · GitBook
13. 배열에 항목 추가하기 이 섹션에서 사용된 코드는 다음 페이지에서 확인 할 수 있습니다. 이번에는 배열에 새로운 항목을 추가하는 방법을 알아보겠습니다. 우선, input 두개와 button 하나로 이
react.vlpt.us
(기존에 쓰던 코드에 이어서)
지금까지 구현된 기능과 컴포넌트 구조를 정리해보자면,
이름, 닉네임을 적을 수 있는 input이 각각 하나씩 있고 등록 버튼이 있다.
그 아래에 3명의 유저 이름과 닉네임이 적혀있고,
내가 input에 이름과 닉네임을 적어서 등록버튼을 누르면 그 밑에 차례대로 해당 이름과 닉네임이 적힌다.
쉽게 말해 유저 등록 명부 같은 것을 만든셈이다.
컴포넌트 구조
구조를 살펴보면,
우선 파일 트리는
App.js > CreateUser.js , UserList.js
App 에서는 상태를 생성하거나, 이것을 관리해주는 함수가 들어있다.
CreateUser에는 입력을 받는 input과 등록버튼 이 있는 컴포넌트가 들어있다.
UserList에는 생성된 항목 (유저의 이름과 닉네임)을 보여주는 컴포넌트가 들어있다.
이 프로세스가 어떤 원리로 이뤄져 있는가?
1. App 컴포넌트
- app 컴포에는 필요한 상태를 만들고 이 상태를 하위 컴포에 props로 전달하여 사용.
import React, { useRef , useState } from "react";
import UserList from "./userList";
import CreateUser from './CreateUser';
function App() {
const [inputs , setInputs] = useState({
username:'',
email:''
});
const { username,email } = inputs;
const onChange = e =>{
const {name,value} = e.target;
setInputs({
...inputs,
[name]:value
});
};
const [users,setUsers] = useState([
{
id:1,
username:'velopert',
email:'csprout@nate.com'
},
{
id:2,
username:'tester',
email:'test@test.com'
},
{
id:3,
username:'tester2',
email:'test2@test.com'
}
])
const nextId = useRef(4);
const onCreate = ()=>{
const user = {
id : nextId.current,
username,
email
};
setUsers([...users,user]);
setInputs({
username:'',
email:''
});
nextId.current += 1;
};
return(
<>
<CreateUser
username = {username}
email = {email}
onChange = {onChange}
onCreate = {onCreate}
/>
<UserList users={users}/>
</>
)
}
export default App;
2. CreateUser 컴포넌트
input 박스 2개, button 1개로 구성
import React from 'react';
function CreateUser({username , email , onChange , onCreate }){
return(
<div>
<input
name="username"
placeholder= "계정명"
onChange={onChange}
value={username}
/>
<input
name="email"
placeholder="이메일"
onChange={onChange}
value={email}
/>
<button onClick={onCreate}>등록</button>
</div>
)
}
export default CreateUser;
3. UserList
등록된 유저의 정보가 보이는 곳.
User라는 컴포넌트를 하위에 따로 만들어서 재사용할 수 있도록 만들어줬다.
또한 map을 이용해서 배열의 값을 렌더링 되게 해줬다.
import React from 'react';
function User({ user }){
return (
<div>
<b>{user.username}</b> <span>({user.email})</span>
</div>
);
}
function UserList({users}){
return(
<div>
{users.map(i =>(
<User user={i} key={i.id}/>
))}
</div>
);
}
export default UserList;
코드를 작성하고 나서도 어떤 원리로 동작되는건지 완벽하게 이해하고 싶었기 때문에 수기로 정리한 내용을 작성하려고 한다.
이 부분은 공부할때 재참고하기엔 부적절할 수 있음. 정리용임
1. inputbox에 내용 입력하면 입력한 값이 실시간으로 밑에 나타나고
초기화버튼을 누르면 입력된 내용이 초기화되고 포커스가 특정 input으로 가게되는 기능.
-
사용한 hooks = 포커스 -useRef() , input - useState({})이용해서 객체형태의 상태 만들기
바뀌는 값을 그대로 보여주려면 onChange가 있어야겠고 , 기존 상태값이 객체 형태였으므로 , spread문법의 객체에서의 활용을 참고해서 만들것.
또한 input이 여러개 이므로 name태그를 이용해서 특정 name키를 가진 input의 value를 컨트롤 해줄 수 있다는 점 - 그 input에 onChange가 발생하면, 해당하는 name태그를 가진 value값에 onChange가 발동 되는 구조.
문법은 [태그값] : 바꿔줄 값(여기서는 value)
useRef를 사용해서 객체를 만들면, 해당 상태에 업데이트가 일어날 때 리렌더링이 되지 않음.
useState와 달리. 왜냐하면 useState는 상태를 바꿔주는 함수를 호출해서 렌더링을 일으키고 그 렌더링이 완료되면 업데이트 된 상태를 조회하는 방식임. 하지만 useRef는 상태를 설정하는 즉시 바로 조회가 가능하기 때문에 렌더링을 다시 할 필요가 없는것
2. 배열 렌더링하기
단순히 그냥 배열을 직접 하드코딩해서 그걸 그냥 화면에 보여줄 수 있음.
이때 User 컴포넌트를 만들어서 재사용이 가능하게 한다던지 map을 사용해서 배열을 뿌려준다던지 하는 부분을 활용해서 만들 수 있음
3. useRef() 로 id 관리하기
"useRef()를 사용할 때 파라미터를 넣어주면 이 값이 .current 값을 수정하고 조회를 할 때는 .current를 조회하면 된다."
여기서는 말그대로 그냥 useRef로 컴포넌트 안에 변수를 (즉 상태를) 만들기만 한것임.
const nextId = useRef()
nextId.current +=1
이렇게 해줬으니까 즉 1,2,3,4,5,6,7... 이런 상태값을 만든다는 의미임. 이걸 새로운 항목이 만들어질 때 id로 쓰겠다는 말이니까
새 항목이 추가 될 때마다 호출될수 있는 함수를 만들어서 그 안에 넣으면 됨.
https://react.vlpt.us/basic/14-array-remove.html
14. 배열에 항목 제거하기 · GitBook
14. 배열에 항목 제거하기 이 섹션에서 사용된 코드는 다음 페이지에서 확인 할 수 있습니다. 이번에는 배열에 항목을 제거 할 때에는 어떻게 해야 하는지 알아보겠습니다. 우선, UserList 에서 각 U
react.vlpt.us
등록된 명부 리스트에 삭제버튼을 추가해줘서
해당 버튼을 누르면 그 순서에 해당하는 유저정보가 사라지게끔 만들기
->
UserList.js
import React from 'react';
function User({ user , onRemove }){
return (
<div>
<b>{user.username}</b> <span>({user.email})</span>
<button onClick={()=> onRemove(user.id)}>삭제</button>
</div>
);
}
function UserList({users , onRemove}){
return(
<div>
{users.map(i =>(
<User user={i} key={i.id} onRemove={onRemove}/>
))}
</div>
);
}
export default UserList;
App.js 해당 부분이 추가적으로 들어감
const onRemove= id =>{
setUsers(users.filter(user => user.id !==id));
};
return(
<>
<CreateUser
username = {username}
email = {email}
onChange = {onChange}
onCreate = {onCreate}
/>
<UserList users={users} onRemove={onRemove}/>
</>
);
개념 1. 리액트에서의 함수 호출
onRemove 함수를 props로 전달해줘서 삭제 버튼을 누르면 해당 함수가 실행되도록 한다.
이때 onClick = {()=>{onRemove(user.id)}}
와 같이 익명 애로우 함수를 사용해주는 이유는
만약 onClick={someFunction()} 을 해주게 되면
해당 컴포넌트가 렌더링 됨과 동시에 someFunction 함수는 실행 된다.
그래서 보통은 onClick = {someFunction} 과 같이 () 을 제외하는 형태로 함수를 호출하게 되는데,
여기서는 인자값으로 user.id를 받아와야 하므로
필연적으로 someFunction(user.id) 과 같은 형식을 사용하게 되는 것이다.
따라서 onClick = {someFunction(user.id)} 를 하게 되면
컴포넌트가 렌더링 되는 시점에서 해당 함수가 실행 되어버려서 결국 화면에는 아무것도 렌더링 되지 않을것이다.
따라서 onClick 에 콜백함수를 넣어줘서 해당 함수가 실행 될 때 user.id를 건내줘서 실행시키는 식으로 처리를 한 것이다.
개념 2. 함수의 인자 전달
onRemove 함수를 App.js 에서 만들어줬을 때 ,
const onRemove = id => {
setUsers(users.filter(user => user.id !== id));
};
이 부분에서 파라미터로 받은 id라는 값이 어디서 나온 것인지 잘 이해가 되지 않았다.
이 함수가 실행되는 button 즉 UserList 컴포넌트를 살펴보면 된다.
여기서보면 button을 누르면 user.id 를 인자값으로 받도록 되어있다.
그러니까 결국 그 상위 컴포넌트에서
users.map을 돌려서 해당하는 번째의 user 객체. 의 id값..!! 을 인자로 던져준것 !
돌아가서 App.js의 onRemove 함수를 보면 ,
파라미터도 이 값을 받아서 filter를 이용해 새로운 배열을 만들어낸 것이다.
그리고 users.filter(user=>user.id) 이 부분은
인자명이 user라서 헷갈렸는데..
결국 그냥 인자라서
users 에 있는 값들을 필터 돌려서 각각 요소요소(여기서는 각 객체)의 id 값 <= 요걸 지칭하는 의미였다.
그래서 해당 요소요소의 아이디 값이랑 & 파라미터로 받아온 id 값 (여기서는 버튼을 누른 해당 객체의 id 값)
이 두개를 비교해서
같은 아이디 값을 가진 객체를 제외하고 새로운 배열을 만들어서
user 상태에 담아준 것이다~