๐ useRef๋ก ์ปดํฌ๋ํธ ๋ด๋ถ ๋ณ์ ์์ฑํ๊ธฐ
๐ ๋ฐฐ์ด์ ํญ๋ชฉ ์ถ๊ฐํ๊ธฐ
๐ ๋ฐฐ์ด์ ํญ๋ชฉ ์ ๊ฑฐํ๊ธฐ
๐ ๋ฐฐ์ด์ ํญ๋ชฉ ์์ ํ๊ธฐ
๐ค ๋ฐฐ์ด ๋๋๋งํ๊ธฐ.
๊ฐ๋ น ์๋์ ๊ฐ์ ๋ฐฐ์ด์ด ์์ ๋,
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' } ];
์ด ๋ด์ฉ์ ์ปดํฌ๋ํธ๋ก ๋๋๋ง ํ๊ณ , ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฌ์ฉ ํ ์ ์๊ฒ ํ๋ค๋ฉด?
UserList.js import React from 'react'; function User({ user }) { return ( <div> <b>{user.username}</b> <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> <User user={users[0]} /> <User user={users[1]} /> <User user={users[2]} /> </div> ); } export default UserList;
๐ค ๋ง์ฝ, ๋์ ์ธ ๋ฐฐ์ด์ ๋๋๋ง ํด์ผํ๋ค๋ฉด? → map() ์ ์ฌ์ฉ!!
map() ํจ์๋ ๋ฐฐ์ด์์ ์๋ ๊ฐ ์์๋ฅผ ๋ณํํ์ฌ ์๋ก์ด ๋ฐฐ์ด์ ๋ง๋ ๋ค.
react์์ ๋์ ์ธ ๋ฐฐ์ด์ ๋๋๋งํด์ผ ํ ๋๋ ์ด ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ผ๋ฐ ๋ฐ์ดํฐ ๋ฐฐ์ด์ react element๋ก ์ด๋ฃจ์ด์ง ๋ฐฐ์ด๋ก ๋ณํํด์ฃผ๋ฉด ๋๋ค.
๋ค๋ง, react์์ ๋ฐฐ์ด์ ๋๋๋งํ ๋๋ key๋ผ๋ props๋ฅผ ์ค์ ํด์ผ ํ๋ค.
UserList.js import React from 'react'; function User({ user }) { return ( <div> <b>{user.username}</b> <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 default UserList;
๋ง์ฝ ๋ฐฐ์ด ์์ ์์๊ฐ ๊ฐ์ง๊ณ ์๋ ๊ณ ์ ํ ๊ฐ์ด ์๋ค๋ฉด map() ํจ์๋ฅผ ์ฌ์ฉ ํ ๋ ์ค์ ํ๋ ์ฝ๋ฐฑํจ์์ ๋๋ฒ์งธ ํ๋ผ๋ฏธํฐ index ๋ฅผ key ๋ก ์ฌ์ฉํ๋ฉด ๋๋ค.Ex)
<div> {users.map((user, index) => ( <User user={user} key={index} /> ))} </div>
cf. useRef (https://chan4im.tistory.com/190)
๐ค useRef๋ก ์ปดํฌ๋ํธ ์์ ๋ณ์ ๋ง๋ค๊ธฐ
useRef์ Hook์ 2๊ฐ์ง ์ฉ๋๊ฐ ์๋ค.
1. DOM ์ ํ ์ฉ๋
2. ์ปดํฌ๋ํธ ์์์ ์กฐํ ๋ฐ ์์ ํ ์ ์๋ ๋ณ์๋ฅผ ๊ด๋ฆฌํ๋ ์ฉ๋
๊ด๋ฆฌ๋ฅผ ์ํ ๋ณ์
โ setTimeout, setInterval์ ํตํด ๋ง๋ค์ด์ง id
โ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด ์์ฑ๋ ์ธ์คํด์ค
โ scroll ์์น
Ex) UserList์์ ์ปดํฌ๋ํธ ๋ด๋ถ์ ๋ฐฐ์ด์ ์ง์ ์ ์ธํ๋ ๋์ , App์์ ๋ฐฐ์ด์ ์ ์ธ, UserList์๊ฒ props๋ก ์ ๋ฌํ๋ ์์
UserList.js 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(user => ( <User user={user} key={user.id} /> ))} </div> ); } export default UserList;
App.js import React, { useRef } from 'react'; import UserList from './UserList'; function App() { 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' } ]; const nextId = useRef(4); const onCreate = () => { // ๋์ค์ ๊ตฌํ ํ ๋ฐฐ์ด์ ํญ๋ชฉ ์ถ๊ฐํ๋ ๋ก์ง // ... nextId.current += 1; }; return <UserList users={users} />; } export default App;
App ์์ useRef() ๋ฅผ ์ฌ์ฉํ์ฌ nextId ๋ผ๋ ๋ณ์๋ฅผ ์์ฑํ๋ฉฐ,
useRef() ๋ฅผ ์ฌ์ฉ ํ ๋ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฃ์ด์ฃผ๋ฉด, ์ด ๊ฐ์ด .current ๊ฐ์ ๊ธฐ๋ณธ๊ฐ์ด ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ด ๊ฐ์ ์์ ํ ๋์๋ .current ๊ฐ์ ์์ ํ๋ฉด ๋๊ณ ์กฐํ ํ ๋์๋ .current ๋ฅผ ์กฐํํ๋ฉด ๋๋ค.
๋จผ์ input 2๊ฐ์ button 1๊ฐ๋ก ์ด๋ฃจ์ด์ง CreateUser.js๋ผ๋ ์ปดํฌ๋ํธ๋ฅผ src๋๋ ํ ๋ฆฌ์ ์ถ๊ฐ
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;
๐ค ๋ฐฐ์ด์ ํญ๋ชฉ ์ถ๊ฐํ๊ธฐ
์์ CreateUser์์ ์ปดํฌ๋ํธ์ ์ํ๊ด๋ฆฌ๋ฅผ ํ์ง ์๊ณ
๋ถ๋ชจ ์ปดํฌ๋ํธ์ธ App์์ ์ํ๊ด๋ฆฌ๋ฅผ ์งํ, input๊ฐ ๋ฐ ์ด๋ฒคํธ ๋ฑ๋ก ํจ์๋ค์ props๋ก ๋๊ฒจ๋ฐ์ ์ฌ์ฉํด๋ณด์.
์ด ์ปดํฌ๋ํธ๋ฅผ App์์ UserList์์ ๋๋๋ง ํด๋ณด์.
App.js import React, { useRef } from 'react'; import UserList from './UserList'; import CreateUser from './CreateUser'; function App() { 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' } ]; const nextId = useRef(4); const onCreate = () => { // ๋์ค์ ๊ตฌํ ํ ๋ฐฐ์ด์ ํญ๋ชฉ ์ถ๊ฐํ๋ ๋ก์ง // ... nextId.current += 1; }; return ( <> <CreateUser /> <UserList users={users} /> </> ); } export default App;
CreateUser ์ปดํฌ๋ํธ์๊ฒ ํ์ํ props๋ฅผ App์์ ์ค๋น,
๊ทธ ํ, users์๋ useState๋ฅผ ์ฌ์ฉํด ์ปดํฌ๋ํธ์ ์ํ๋ก์ ๊ด๋ฆฌ.
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 = () => { // ๋์ค์ ๊ตฌํ ํ ๋ฐฐ์ด์ ํญ๋ชฉ ์ถ๊ฐํ๋ ๋ก์ง // ... setInputs({ username: '', email: '' }); nextId.current += 1; }; return ( <> <CreateUser username={username} email={email} onChange={onChange} onCreate={onCreate} /> <UserList users={users} /> </> ); } export default App;
์ด์ ๋ฐฐ์ด์ ๋ณํ๋ฅผ ์ค์ผํ๋๋ฐ, ์ด๋ ๊ฐ์ฒด์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ถ๋ณ์ฑ์ ์ง์ผ์ค์ผ ํ๋ค.
๋ฐ๋ผ์ ๋ฐฐ์ด์ push, splice, sort ๋ฑ์ ํจ์๋ ์ฌ์ฉX
if, ์ฌ์ฉํด์ผํ ๋, ๊ธฐ์กด ๋ฐฐ์ด์ ํ๋ฒ ๋ณต์ฌํ ํ ์ฌ์ฉํด์ผํจ.
๐ ๋ถ๋ณ์ฑ์ ์งํค๋ฉด์ ๋ฐฐ์ด์ ์ ํญ๋ชฉ์ ์ถ๊ฐํ๋ ๋ฐฉ๋ฒ
1. spread ์ฐ์ฐ์ ์ฌ์ฉ
2. concat ํจ์ ์ฌ์ฉ
- 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;
- 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)); setInputs({ username: '', email: '' }); nextId.current += 1; }; return ( <> <CreateUser username={username} email={email} onChange={onChange} onCreate={onCreate} /> <UserList users={users} /> </> ); } export default App;
์ฐ์ , UserList์ ๊ฐ User ์ปดํฌ๋ํธ์ ๋ํด ์ญ์ ๋ฒํผ์ ๋๋๋ง.
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} />
))}
</div>
);
}
export default UserList;
๐ค ๋ฐฐ์ด์ ํญ๋ชฉ ์ ๊ฑฐํ๊ธฐ
์ด๋, User ์ปดํฌ๋ํธ์ ์ญ์ ๋ฒํผ์ด ํด๋ฆญ๋ ๋, user.id๊ฐ์ ์์ผ๋ก props๋ก ๋ฐ์์ฌ onRemove ํจ์์ ํ๋ผ๋ฏธํฐ๋ก ๋ฃ์ด ํธ์ถํด์ผ
ํ๋ค. (onRemoveํจ์๋ "id๊ฐ ~์ธ ๊ฐ์ฒด๋ฅผ ์ญ์ ํ๋ผ"๋ ์ญํ )
์ด๋, onRemoveํจ์๋ UserList์์๋ ์ ๋ฌ๋ฐ๊ณ , ์ด๋ฅผ ๊ทธ๋๋ก User ์ปดํฌ๋ํธ์๊ฒ ์ ๋ฌํ๋ค.
์ด์ onRemove๋ฅผ ๊ตฌํํด๋ณด์.
๋ฐฐ์ด์ ์๋ ํญ๋ชฉ์ ๊ฑฐ ์, ์ถ๊ฐํ ๋์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ถ๋ณ์ฑ์ ์ง์ผ๊ฐ๋ฉฐ ์ ๋ฐ์ดํธ ํด์ค์ผ ํ๋ค.
์ด๋, filter๋ผ๋ ๋ฐฐ์ด ๋ด์ฅ ํจ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์ถ์ฒ!!
App.jsimport 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 => { // 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} /> </> ); } export default App;
๋จผ์ App ์ปดํฌ๋ํธ์ users ๋ฐฐ์ด ์์ ๊ฐ์ฒด ์์ 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 => {
// 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;โ
๐ค ๋ฐฐ์ด์ ํญ๋ชฉ ์์ ํ๊ธฐ
User ์ปดํฌ๋ํธ์ ๊ณ์ ๋ช ํด๋ฆญ ์, ์์์ด ์ด๋ก์์ผ๋ก ๋ฐ๋๊ณ ๋ค์ ๋๋ฅด๋ฉด ๊ฒ์ ์์ผ๋ก ๋ฐ๋๋๋ก ํ๋ ๊ตฌํ
์ด์ , User ์ปดํฌ๋ํธ์์ active ๊ฐ์ ๋ฐ๋ผ ํฐํธ์์ด ๋ฐ๋๋๋ก ํด๋ณด์.
cf. cursor ํ๋๋ฅผ ์ค์ ํด ๋ง์ฐ์ค๋ฅผ ์ฌ๋ ธ์ ๋, ์๊ฐ๋ฝ ๋ชจ์์ผ๋ก ๋ฐ๋๋๋ก ํ์.
UserList.js import React from 'react'; function User({ user, onRemove }) { return ( <div> <b style={{ cursor: 'pointer', color: user.active ? 'green' : 'black' }} > {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;
์ด์ App.js ์์ onToggle ์ด๋ผ๋ ํจ์๋ฅผ ๊ตฌํ,
๋ฐฐ์ด์ ๋ถ๋ณ์ฑ์ ์ ์งํ๋ฉด์ ๋ฐฐ์ด์ ์ ๋ฐ์ดํธ ํ ๋์๋ map ํจ์๋ฅผ ์ฌ์ฉ ํ ์ ์๋ค.id ๊ฐ์ ๋น๊ตํด์ id ๊ฐ ๋ค๋ฅด๋ค๋ฉด ๊ทธ๋๋ก ๋๊ณ , ๊ฐ๋ค๋ฉด active ๊ฐ์ ๋ฐ์ ์ํค๋๋ก ๊ตฌํ์ ์งํ,
onToggle ํจ์๋ฅผ ๋ง๋ค์ด์ 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 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 => { // user.id ๊ฐ ํ๋ผ๋ฏธํฐ๋ก ์ผ์นํ์ง ์๋ ์์๋ง ์ถ์ถํด์ ์๋ก์ด ๋ฐฐ์ด์ ๋ง๋ฌ // = user.id ๊ฐ id ์ธ ๊ฒ์ ์ ๊ฑฐํจ setUsers(users.filter(user => user.id !== id)); }; const onToggle = id => { setUsers( users.map(user => user.id === id ? { ...user, active: !user.active } : user ) ); }; return ( <> <CreateUser username={username} email={email} onChange={onChange} onCreate={onCreate} /> <UserList users={users} onRemove={onRemove} onToggle={onToggle} /> </> ); } export default App;
๊ทธ ๋ค์์๋ UserList ์ปดํฌ๋ํธ์์ onToggle๋ฅผ ๋ฐ์์์ User ์๊ฒ ์ ๋ฌํด์ฃผ๊ณ , onRemove ๋ฅผ ๊ตฌํํ์๋๊ฒ์ฒ๋ผ onToggle ์ id ๋ฅผ ๋ฃ์ด์ ํธ์ถํ์.
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;
'ETC(front,back) > React(HTML, CSS, JS)' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
<frontend> {15} </React_part 2. ๋์ interaction> (0) | 2023.07.11 |
---|---|
<frontend> {14} </React_part 1. Basic> (0) | 2023.07.11 |
<frontend> {13} </JS์ ๊ฐ์ฒด, ๋ฌธ์๊ฐ์ฒด๋ชจ๋ธ(DOM)> (0) | 2023.07.05 |
<frontend> {12} </JS๊ธฐ๋ณธ ๋ฌธ๋ฒ, let๊ณผ const, onclick> (0) | 2023.07.05 |
<frontend> {11} </Javascript ๊ธฐ์ด์ฉ์ด ๋ฐ ์ ์ถ๋ ฅ ๋ฐฉ๋ฒ> (0) | 2023.07.05 |