react 스터디에서 리액트를 다루는 기술이라는 책을 선정했고 이 책을 읽고 배운 것을 바탕으로 작성되었다.
Array.prototype.map(callback(currentValue, index, array), thisArg)
currentValue
: 현재 처리할 요소 값index
: 현재 요소의 인덱스 값array
: 메서드를 호출한 배열thisArg
: 콜백함수를 실행할 때 사용할 this
function User({user}){
return(
<div>
<span>{user.username}</span>
<span>({user.email})</span>
</div>
);
}
function UserList(){
const users = [
{
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'
}
];
return (
<div>
users.map(user => <User user = {user} key = {user.id}/>);
</div>
);
}
export defalut UserList;
💡 Key
는 React가 어떤 항목을 변경, 추가 또는 삭제할지 식별하는 것을 돕는다.
key
값은 다른 항목들 사이에서 해당 항목을 고유하게 식별할 수 있는 값으로 설정해야 한다.index
값을 key
값으로 사용하면 된다.key
는 배열 안 형제 사이에서 고유해야 하고 전체 범위에서 고유할 필요는 없다.const array = ['a', 'b', 'c', 'd'];
array.map(item => <div>{item}</div>);
<div>b</div>
와 <div>c</div>
사이에 새 div
태그를 삽입을 하게 되는 것이 아니라, 기존의 c 가 z 로바뀌고, d 는 c 로 바뀌고, 맨 마지막에 d 가 새로 삽입된다.const array = [
{
id: 0,
text: 'a'
},
{
id: 1,
text: 'b'
},
{
id: 2,
text: 'c'
},
{
id: 3,
text: 'd'
}
];
array.map(item => <div key={item.id}>{item.text}</div>);
key
값이 있는 것이 중요하다.key
가 있을 때에는 렌더링 시에 오류 메시지가 콘솔에 나타나게 되며, 업데이트가 제대로 이루어지지 않게 된다.spread
연산자 사용concat
메서드 사용state
나 props
가 변경될 때마다 re-rendering
되는데, 함수형 컴포넌트는 내부에 정의된 로컬 변수들을 초기화한다.useRef
로 만들어진 객체는 React가 만든 전역 저장소에 저장되기 때문에 리렌더링되더라도 마지막으로 업데이트한 current 값이 유지된다.// UserList.js
function User({user}){
return(
<div>
<span>{user.username}</span>
<span>({user.email})</span>
</div>
);
}
function UserList({users}){
return (
<div>
users.map(user => <User user = {user} key = {user.id}/>);
</div>
);
}
export defalut UserList;
// CreateUser.js
function CreateUser({username, email, onChange, onCreate}){
return (
<div>
<input
type="text",
name="username",
value={username}
onChange={onChange}
placeholder="계정명"/>
<input
type="email"
name="email"
value={email}
onChange={onChange}
placeholder="이메일"/>
<button onClick = {onCreate}>등록</button>
</div>
);
}
export default Createuser;
// 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 [users, setUsers] = userState([
{
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 onChange = (e) => {
const { name, value } = e.target;
setInputs({
...inputs,
[name]: value
});
};
const onCreate = () => {
const newUser = {
id: nextId.current;
username,
email
};
setUsers([...user, newUser ]); // spread 연산자 이용
// setUsers(user.concat(newUser)); // concat 메서드 이용
setInputs({
username: "",
email: ""
});
nextId.current++;
}
return (
<div>
<CreateUser
username={username}
email={email}
onChange={onChange}
onCreate={onCreate}
/>
<UserList users={users} />
</div>
);
}
export default Createuser;
Array.prototype.filter(callback(currentValue, index, array), thisArg)
currentValue
: 현재 처리할 요소 값index
: 현재 요소의 인덱스 값array
: 메서드를 호출한 배열thisArg
: 콜백함수를 실행할 때 사용할 this
// UserList.js
function User({user, onRemove}){
return(
<div>
<span>{user.username}</span>
<span>({user.email})</span>
<button onClick={() => onRemove(user.id)}>삭제</button>
</div>
);
}
function UserList({users, onRemove}){
return (
<div>
users.map(user => <User user = {user} onRemove={onRemove} key = {user.id}/>);
</div>
);
}
export defalut UserList;
// 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 [users, setUsers] = userState([
{
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 onChange = (e) => {
const { name, value } = e.target;
setInputs({
...inputs,
[name]: value
});
};
const onCreate = () => {
const newUser = {
id: nextId.current;
username,
email
};
setUsers([...users, newUser ]); // spread 연산자 이용
// setUsers(users.concat(newUser)); // concat 메서드 이용
setInputs({
username: "",
email: ""
});
nextId.current += 1;
}
const noRemove = (id) => {
setUsers(users.filter(user => user.id !== id));
}
return (
<div>
<CreateUser
username={username}
email={email}
onChange={onChange}
onCreate={onCreate}
/>
<UserList users={users} onRemove={onRemove}/>
</div>
);
}
export default Createuser;
onRemove
라는 이벤트 핸들러를 계속 props
로 전달하여 최종적으로 User
컴포넌트에 전달<button onClick={() => onRemove(user.id)}>삭제</button>
User 컴포넌트에 계정명을 클릭했을때 색상이 초록색으로 바뀌고, 다시 누르면 검정색으로 바뀌도록 구현
// UserList.js
function User({user, onRemove, onToggle}){
return(
<div>
<span
onClick={() => onToggle(user.id)}
style = {{
cursor: "pointer",
color: user.active ? "green" : "black"
}}
>{user.username}</span>
<span>({user.email})</span>
<button onClick={() => onRemove(user.id)}>삭제</button>
</div>
);
}
function UserList({users, onRemove, onToggle}){
return (
<div>
users.map(user =>
<User
user = {user}
onRemove={onRemove}
onToggle={onToggle}
key={user.id}
/>
);
</div>
);
}
export defalut UserList;
// 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 [users, setUsers] = userState([
{
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 onChange = (e) => {
const { name, value } = e.target;
setInputs({
...inputs,
[name]: value
});
};
const onCreate = () => {
const newUser = {
id: nextId.current;
username,
email
};
setUsers([...users, newUser ]); // spread 연산자 이용
// setUsers(users.concat(newUser)); // concat 메서드 이용
setInputs({
username: "",
email: ""
});
nextId.current += 1;
}
const onRemove = (id) => {
setUsers(users.filter(user => user.id !== id));
}
const onToggle = (id) => {
setUsers(users.map(user =>
user.id === id ? {...user, user.active: !user.active} : user
);
};
return (
<div>
<CreateUser
username={username}
email={email}
onChange={onChange}
onCreate={onCreate}
/>
<UserList users={users} onRemove={onRemove} onToggle={onToggle}/>
</div>
);
}
export default Createuser;
참고