이 글은 velopert님의 벨로퍼트와 함께하는 모던 리액트를 참고하여 쓴 글 입니다.
배열에 요소 추가하기
배열에 항목을 추가한다는 것은 변화를 주는 것이기 때문에 리액트에서의 불변성을 지켜주어야 한다.
따라서 useState
에 등록된 setter
에서 변화를 줄때, 배열의 push
, splice
, sort
등의 함수는 사용할 수 없다.
불변성을 지키면서 배열에 항목을 추가하는 방법 2가지
- spread연산자를 사용하는 방법
- concat 함수를 사용하는 방법
CreateUser.js 생성
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;
1. spread 연산자를 사용하는 방법
App.js
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: 'public.velopert@gmail.com'
},
{
id: 2,
username: 'tester',
email: 'tester@example.com'
},
{
id: 3,
username: 'liz',
email: 'liz@example.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. concat함수를 이용하는 방법
App.js
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: 'public.velopert@gmail.com'
},
{
id: 2,
username: 'tester',
email: 'tester@example.com'
},
{
id: 3,
username: 'liz',
email: 'liz@example.com'
}
]);
const nextId = useRef(4);
const onCreate = () => {
const user = {
id: nextId.current,
username,
email
};
setUsers(users.concat(user)); // concat함수를 이용해서 불변성을 지킴
setInputs({
username: '',
email: ''
});
nextId.current += 1;
};
return (
<>
<CreateUser
username={username}
email={email}
onChange={onChange}
onCreate={onCreate}
/>
<UserList users={users} />
</>
);
}
export default App;
배열에 새 항목을 추가 할 때에는 spread 연산자를 사용하거나, concat
함수를 사용하면 된다.
배열에서 요소 삭제하기
삭제 버튼 렌더링
- 배열에 항목을 제거하기 위해 먼저 User 컴포넌트에서 삭제 버튼을 렌더링해준다.
- 또한 후에 추가할 삭제하는 기능을 가진
onRemove
함수를props
로 전달 받는다.
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(user => (
<User user={user} key={user.id} onRemove={onRemove} /> // User컴포넌트로 삭제함수 전달
))}
</div>
);
}
export default UserList;
삭제 버튼에 부여해줄 로직 설정
삭제 버튼이 클릭 될때, user.id
값을 onRemove
함수의 파라미터로 받아와서 호출해 줘야 한다.
onRemove
는 id가 user.id
와 일치하는 객체를 삭제하는 역할을 가진다.
onRemove
함수는 App.js에서 UserList 컴포넌트로 전달되며, 그대로 User컴포넌트에도 전달이 된다.
App.js
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: 'public.velopert@gmail.com'
},
{
id: 2,
username: 'tester',
email: 'tester@example.com'
},
{
id: 3,
username: 'liz',
email: 'liz@example.com'
}
]);
const nextId = useRef(4);
const onCreate = () => {
const user = {
id: nextId.current,
username,
email
};
setUsers(users.concat(user));
setInputs({
username: '',
email: ''
});
nextId.current += 1;
};
const onRemove = id => { // onRemove 함수 생성
// user.id 가 파라미터로 일치하지 않는 원소만 추출해서 새로운 배열을 만듬
// = user.id 가 id 인 것을 제거함
setUsers(users.filter(user => user.id !== id));
};
return (
<>
<CreateUser
username={username}
email={email}
onChange={onChange}
onCreate={onCreate}
/>
<UserList users={users} onRemove={onRemove} /> // onRemove함수 UserList로 전달
</>
);
}
export default App;
배열에서 요소 수정하기
User 컴포넌트에서 계정명을 클릭했을때 색상이 초록색으로 바뀌고, 다시 누르면 검정색으로 바뀌도록 구현
색상을 표현하는 기준이 될 active
속성을 users 객체에 추가해준다.
수정할 요소를 users 객체에 추가
App.js
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: 'public.velopert@gmail.com',
active: true // active 속성 추가
},
{
id: 2,
username: 'tester',
email: 'tester@example.com',
active: false // active 속성 추가
},
{
id: 3,
username: 'liz',
email: 'liz@example.com',
active: false // active 속성 추가
}
]);
const nextId = useRef(4);
const onCreate = () => {
const user = {
id: nextId.current,
username,
email
};
setUsers(users.concat(user));
setInputs({
username: '',
email: ''
});
nextId.current += 1;
};
const onRemove = id => {
// user.id 가 파라미터로 일치하지 않는 원소만 추출해서 새로운 배열을 만듬
// = user.id 가 id 인 것을 제거함
setUsers(users.filter(user => user.id !== id));
};
return (
<>
<CreateUser
username={username}
email={email}
onChange={onChange}
onCreate={onCreate}
/>
<UserList users={users} onRemove={onRemove} onToggle={onToggle} />
</>
);
}
export default App;
추가한 속성의 값에 따라 색상이 바뀌도록 구현
추가한 active의 값에 따라서 user.name
을 표현하는 태그의 style 속성을 변경시켜 준다.
UserList.js
import React from 'react';
function User({ user, onRemove }) {
return (
<div>
<b
style={{
cursor: 'pointer', // 마우스를 올렷을때 커서가 손가락 모양으로 바뀜
color: user.active ? 'green' : 'black' // active 값에 따라 color 스타일 지정
}}
>
{user.username}
</b>
<span>({user.email})</span>
<button onClick={() => onRemove(user.id)}>삭제</button>
</div>
);
}
function UserList({ users, onRemove }) {
return (
<div>
{users.map(user => (
<User user={user} key={user.id} onRemove={onRemove} />
))}
</div>
);
}
export default UserList;
기본값이 true인 요소가 초록색으로 나타난다.
클릭시 색이 변하는 기능 구현
- 클릭시 발생하는
onToggle
함수를 생성해서 id 값을 비교해 같은 값이면 active값을 반전시키도록 구현
App.js
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: 'public.velopert@gmail.com',
active: true
},
{
id: 2,
username: 'tester',
email: 'tester@example.com',
active: false
},
{
id: 3,
username: 'liz',
email: 'liz@example.com',
active: false
}
]);
const nextId = useRef(4);
const onCreate = () => {
const user = {
id: nextId.current,
username,
email
};
setUsers(users.concat(user));
setInputs({
username: '',
email: ''
});
nextId.current += 1;
};
const onRemove = id => {
setUsers(users.filter(user => user.id !== id));
};
const onToggle = id => { // onToggle함수 생성
setUsers(
users.map(user => // map함수를 이용해서 user.id와 파라미터의 id를 비교
user.id === id ? { ...user, active: !user.active } : user // 같은 값이면 active값을 반전
)
);
};
return (
<>
<CreateUser
username={username}
email={email}
onChange={onChange}
onCreate={onCreate}
/>
<UserList users={users} onRemove={onRemove} onToggle={onToggle} /> {//onToggle함수 UserList컴포넌트로 전달}
</>
);
}
export default App;
UserList에서 전달받은 onToggle
함수를 User 컴포넌트에 전달해주고, 해당 함수를 user.username
이 보여지는 태그에 등록
UserList.js
import React from 'react';
function User({ user, onRemove, onToggle }) {
return (
<div>
<b
style={{
cursor: 'pointer',
color: user.active ? 'green' : 'black'
}}
onClick={() => onToggle(user.id)}
>
{user.username}
</b>
<span>({user.email})</span>
<button onClick={() => onRemove(user.id)}>삭제</button>
</div>
);
}
function UserList({ users, onRemove, onToggle }) {
return (
<div>
{users.map(user => (
<User
user={user}
key={user.id}
onRemove={onRemove}
onToggle={onToggle}
/>
))}
</div>
);
}
export default UserList;
계정명을 눌러서 색이 바뀌는지 확인 해보기
정리
배열에 요소 추가
- useState의 setter에서 리액트의 불변성을 지키면서 해당 요소를 추가할것
- Spread연산자 사용하는 방법
setUsers([...users, user]);
- concat함수 사용하는 방법
setUsers(users.concat(user));
배열 요소 삭제
filter
를 통해서 조건을 만족하는 값 추출
const onRemove = id => {
setUsers(users.filter(user => user.id !== id));
};
- 태그에서 변수를 전달할때는 화살표 함수를 통해서 전달
<button onClick={() => onRemove(param)}>
배열 요소 수정
- 배열의 불변성을 유지하면서 업데이트 할 때에도
map
함수를 사용
const onToggle = id => { // onToggle함수 생성
setUsers(
users.map(user => // map함수를 이용해서 user.id와 파라미터의 id를 비교
user.id === id ? { ...user, active: !user.active } : user // 같은 값이면 active값을 반전
)
);
};
참고글
https://react.vlpt.us/basic/15-array-modify.html