[React] ๋ฆฌ์กํธ ์ฝ๋๋ฅผ ๊ฐ์ ํ ์ ์๋ 4๊ฐ์ง ํ
TLDR
- ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ์ปค๋ง ํ์ฉ
- ์ปดํฌ๋ํธ ์ฑ ์ ๋ถ๋ฆฌ
- ์กฐ๊ฑด๋ฌธ ๋์ ๊ฐ์ฒด map ์ฌ์ฉ
- React ๋ผ์ดํ์ฌ์ดํด ์ธ๋ถ์ ๋ ๋ฆฝ์ ์ธ ๋ณ์ ๋ฐฐ์น
4 React Tips
1. ์ปค๋ง ํ์ฉ
user ์ํ๋ name, surname, address 3๊ฐ ์์ฑ์ ๊ฐ์ง๋ฉฐ, ์ด์ ๋์ํ๋ 3๊ฐ์ input ํ๋๊ฐ ํ์ํ๋ค. ์๋ ์ฝ๋์์ ๊ฐ ํ๋๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด ๋ณ๋์ ํธ๋ค๋ฌ๋ฅผ ๊ฐ๊ฐ ๋ง๋ค์ด์ ์ฌ์ฉํ๊ณ ์์ง๋ง, ์ด ํธ๋ค๋ฌ๋ค์ value๊ฐ ํ ๋ฌ๋ ์์ฑ ์ด๋ฆ๋ง ๋ค๋ฅผ ๋ฟ ๋๋จธ์ง ๋ก์ง์ด ๋์ผํ๊ธฐ ๋๋ฌธ์ ์ฝ๋ ์ค๋ณต์ด ๋ฐ์ํ๊ณ ์๋ค.
export default function App() {
const [user, setUser] = useState({
name: "",
surname: "",
address: "",
});
const handleNameChange = (e) => {
setUser((prev) => ({
...prev,
name: e.target.value,
}));
};
const handleSurnameChange = (e) => {
setUser((prev) => ({
...prev,
surname: e.target.value,
}));
};
const handleAddressChange = (e) => {
setUser((prev) => ({
...prev,
address: e.target.value,
}));
};
return (
<>
<input value={user.name} onChange={handleNameChange} />
<input value={user.surname} onChange={handleSurnameChange} />
<input value={user.address} onChange={handleAddressChange} />
</>
);
}
ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์์ ์์ฃผ ์ฌ์ฉํ๋ ์ปค๋ง์ n๊ฐ์ ์ธ์๋ฅผ ๋ฐ๋ ๋์ n๊ฐ์ ํจ์๋ฅผ ๋ง๋ค์ด์ ํ๋์ ์ธ์๋ง ๋ฐ๋๋ก ๋ง๋๋ ํจํด์ด๋ค.
currying is the technique of translating a function that takes multiple arguments into a sequence of families of functions, each taking a single argument.
์ปค๋ง ํจํด์ ์ ์ฉํ์ฌ ๊ธฐ์กด ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ๊ฐ ์์ฑ์ ๋์ํ๋ ํจ์๋ฅผ ๋ฐํํ๋๋ก ๋ง๋ค๋ฉด, ํน์ ํ๋์ ๋ง๋ ํธ๋ค๋ฌ๋ฅผ ๋์ ์ผ๋ก ์์ฑํ ์ ์์ด ์ค๋ณต ์ฝ๋๋ฅผ ์ค์ผ ์ ์๋ค.
export default function App() {
const [user, setUser] = useState({
name: "",
surname: "",
address: "",
});
const handleInputChange = (field) => {
// ๋ฐํ๋ ํธ๋ค๋ฌ
return (e) => {
setUser((prev) => ({
...prev,
[field]: e.target.value,
}));
};
};
return (
<>
<input value={user.name} onChange={handleInputChange("name")} />
<input value={user.surname} onChange={handleInputChange("surname")} />
<input value={user.address} onChange={handleInputChange("address")} />
{JSON.stringify(user)}
</>
);
}
2. ์ฑ ์ ๋ถ๋ฆฌ
1๊ฐ ์ปดํฌ๋ํธ์ ๋๋ฌด ๋ง์ ์ฝ๋ ๋ผ์ธ์ ํฌํจํ๋ฉด ์ ์ง๋ณด์ํ๊ธฐ ํ๋ค๊ณ ์ดํดํ๊ธฐ๋ ์ฝ์ง ์๋ค. ์ด๋ฌํ ์ปดํฌ๋ํธ๋ ์๋์ ๊ฐ์ ๊ธฐ์ค์ ๊ฐ์ง๊ณ ๋ ๋ฆฝ์ ์ธ ํ์ ๋ชจ๋๋ก ๋ถ๋ฆฌํ๋ ๊ฒ์ด ์ข๋ค.
- UI ๋ชจ๋ : ์๊ฐ์ ์ธ ํ๋ฉด๋ง ๋ด๋น
- Logic/Model ๋ชจ๋: ๋น์ฆ๋์ค ๋ก์ง๋ง ํฌํจ e.g., ์ปค์คํ ํ
- Lib ๋ชจ๋: ์ปดํฌ๋ํธ์ ํ์ํ ์ ํธ๋ฆฌํฐ ๋ชจ์
์๋ ListComponent๋ ๋ก์ปฌ ์ํ ๊ด๋ฆฌ, ๋ฐ์ดํฐ ํจ์นญ, ์์ดํ
์ญ์ ๋ฑ ๋ค์ํ ๋ก์ง์ด ํผ์ฌ๋์ด ์๋ค. ์ด ์ปดํฌ๋ํธ์ ๊ด์ฌ์ฌ๋ฅผ ๋ถ๋ฆฌํ์ฌ ๊ฐ์ ํด๋ณด์.
export function ListComponent() {
// ๋ก์ปฌ ์ํ
const [list, setList] = useState([]);
// ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์จ ํ ๋ก์ปฌ ์ํ๋ฅผ ์
๋ฐ์ดํธํ๋ ํจ์
const fetchList = async () => {
try {
const resp = await fetch("https://www.url.com/list");
const data = await resp.json();
setList(data);
} catch {
showAlert({ text: "Something went wrong!" });
}
};
// ์ปดํฌ๋ํธ๊ฐ ์ฒ์ ๋ง์ดํธ ๋ ๋ fetch
useEffect(() => {
fetchList();
}, []);
// ์์ดํ
์ญ์ ๋ฐ ์ํ ์
๋ฐ์ดํธ ํจ์
const handleDeleteItem = (id) => {
return () => {
try {
fetch(`https://www.url.com/list/${id}`, {
method: "DELETE",
});
setList((prev) => prev.filter((x) => x.id !== id));
} catch {
showAlert({ text: "Something went wrong!" });
}
};
};
// ๋ฆฌ์คํธ ๋ทฐ ๋ ๋๋ง
return (
<div className="list-component">
{list.map(({ id, name }) => (
<div key={id} className="list-component__item>">
{/* 30์๋ฅผ ์ด๊ณผํ๋ ์ด๋ฆ์ ... ์๋ต ๋ถํธ ์ถ๊ฐ */}
{name.slice(0, 30) + (name.length > 30 ? "..." : "")}
<div onClick={handleDeleteItem(id)} className="list-component__icon">
<DeleteIcon />
</div>
</div>
))}
</div>
);
}
๋จผ์ Model๊ณผ UI ๋ชจ๋์์ ์ฌ์ฉํ ์ ํธ๋ฆฌํฐ ํจ์๋ฅผ ๋ถ๋ฆฌํ๋ค.
export async function getList(onSuccess) {
try {
const resp = await fetch("https://www.url.com/list");
const data = await resp.json();
onSuccess(data);
} catch {
showAlert({ text: "Something went wrong!" });
}
}
export async function deleteListItem(id, onSuccess) {
try {
fetch(`https://www.url.com/list/${id}`, {
method: "DELETE",
});
onSuccess();
} catch {
showAlert({ text: "Something went wrong!" });
}
}
export function trimName(name) {
return name.slice(0, 30) + (name.length > 30 ? "..." : "");
}
์ํ ๊ด๋ฆฌ์ ๋น์ฆ๋์ค ๋ก์ง์ ๋ณ๋์ ์ปค์คํ ํ ์ผ๋ก ๋ถ๋ฆฌํ๋ค.
export function useList() {
const [list, setList] = useState([]);
// id๋ฅผ ๋ฐ์ ์ด๋ฅผ ์ฒ๋ฆฌํ๋ ํธ๋ค๋ฌ ๋ฐํ
const handleDeleteItem = useCallback((id) => {
return () => {
deleteListItem(id, () => {
setList((prev) => prev.filter((x) => x.id !== id));
});
};
}, []);
useEffect(() => {
getList(setList);
}, []);
return {
list,
handleDeleteItem,
};
}
๋ฆฌ์คํธ ์์ดํ ์ ๋ณ๋์ ์ปดํฌ๋ํธ๋ก ๋ถ๋ฆฌํ์ฌ UI ๋ชจ๋์ ์์ฑํ๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๊ฐ ์์ดํ ์ ๋ ๋๋ง ๋ก์ง์ ๋ ๋ฆฝ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์๋ค.
export function ListComponentItem({ name, onDelete }) {
return (
<div className="list-component__item>">
{trimName(name)}
<div onClick={onDelete} className="list-component__icon">
<DeleteIcon />
</div>
</div>
);
}
์ ํธ๋ฆฌํฐ ํจ์, ์ปค์คํ ํ , UI ์ปดํฌ๋ํธ ๋ฑ์ ๋ชจ๋์ ํตํฉํ๋ค. ์ด๋ก์จ ์ฝ๋์ ์์ง๋(ํ๋์ ๋ชฉ์ ์ ์ํํ๊ธฐ ์ํ ์์ ๊ธฐ๋ฅ๋ค์ ์ฐ๊ด์ฑ์ ๋ฐ๋ผ ๋ชจ๋์ ์ ๋ชจ์๋จ๋์ง ์ฌ๋ถ)๊ฐ ๋์์ง๊ณ ์ ์ง๋ณด์๊ฐ ๋ ์ฉ์ดํด์ก๋ค.
export function ListComponent() {
const { list, handleDeleteItem } = useList();
return (
<div className="list-component">
{list.map(({ id, name }) => (
<ListComponentItem
key={id}
name={name}
onDelete={handleDeleteItem(id)}
/>
))}
</div>
);
}
3. ๊ฐ์ฒด map ์ฌ์ฉ
๋ณ์์ ์ํ์ ๋ฐ๋ผ ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํด์ผ ํ ๋, ์กฐ๊ฑด๋ฌธ์ ์ฌ์ฉํ์ฌ ๊ฐ ์ํ์ ๋ง๋ ์ปดํฌ๋ํธ๋ฅผ ์ ํํ ์ ์๋ค. ํ์ง๋ง ์กฐ๊ฑด๋ฌธ์ด ๋ง์์ง์๋ก ๊ฐ๋ ์ฑ์ด ํ์ ํ๊ฒ ๋จ์ด์ง๋ ๋จ์ ์ด ์๋ค. ๊ฐ์ฒด ๋งต(map)์ ํ์ฉํ๋ฉด ์ฝ๋๋ฅผ ๋์ฑ ๊ฐ๊ฒฐํ๊ณ ์ ์ธ์ ์ผ๋ก ์์ฑํ ์ ์๋ค.
function Account({ type }) {
let Component = UsualAccount;
if (type === "vip") {
Component = VipAccount;
}
if (type === "moderator") {
Component = ModeratorAccount;
}
if (type === "admin") {
Component = AdminAccount;
}
return (
<div className="account">
<Component />
<AccountStatistics />
</div>
);
}
์๋์ฒ๋ผ ๊ฐ์ฒด ๋งต ACCOUNTS_MAP์ ์ฌ์ฉํ์ฌ type๊ณผ ์ปดํฌ๋ํธ๋ฅผ ๋งคํํ๋ฉด ์กฐ๊ฑด๋ฌธ ์์ด๋ ํ์ํ ์ปดํฌ๋ํธ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค. type์ด ๊ฐ์ง๋ ์ํ์ ์ข
๋ฅ๊ฐ ๋ง์์ง ์๋ก ์ด ๋ฐฉ๋ฒ์ด ํนํ ์ ์ฉํ๋ค.
const ACCOUNTS_MAP = {
vip: VipAccount,
usual: UsualAccount,
admin: AdminAccount,
moderator: ModeratorAccount,
};
function Account({ type }) {
const Component = ACCOUNTS_MAP[type];
return (
<div className="account">
<Component />
<AccountStatistics />
</div>
);
}
4. ๋ ๋ฆฝ์ ์ธ ๋ณ์ ๋ฐฐ์น
๋ฆฌ์กํธ์ ๋ผ์ดํ์ฌ์ดํด ๋ฉ์๋๋ฅผ ํ์๋ก ํ์ง ์๋ ๋ก์ง์ ์ปดํฌ๋ํธ์์ ๋ถ๋ฆฌํ๋ ๊ฒ์ด ์ข๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง๋ ๋ ๋ถํ์ํ๊ฒ ์ฌ์ ์ธ๋๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์๊ณ , ์์กด์ฑ์ด ๋ ๋ช ํํด์ ธ์ ์ฝ๋ ๊ฐ๋ ์ฑ์ด ์ข์์ง๋ค.
function useItemsList() {
const defaultItems = [1, 2, 3, 4, 5];
const [items, setItems] = useState(defaultItems);
const toggleArrayItem = (arr, val) => {
return arr.includes(val) ? arr.filter((el) => el !== val) : [...arr, val];
};
const handleToggleItem = (num) => {
return () => {
setItems(toggleArrayItem(items, num));
};
};
return {
items,
handleToggleItem,
};
}
defaultItems ๋ณ์์ toggleArrayItem ํจ์๋ ํน์ ์ปดํฌ๋ํธ์ ์ข
์๋์ง ์๊ธฐ ๋๋ฌธ์ ๋
๋ฆฝ์ ์ธ ์ ํธ๋ฆฌํฐ๋ก ๋ถ๋ฆฌํ ์ ์๋ค. ํ์์ ๋ค๋ฅธ ๊ณณ์์ ์ฝ๊ฒ ์ฌ์ฌ์ฉํ ์๋ ์๋ค.
const DEFAULT_ITEMS = [1, 2, 3, 4, 5];
const toggleArrayItem = (arr, val) => {
return arr.includes(val) ? arr.filter((el) => el !== val) : [...arr, val];
};
function useItemsList() {
const [items, setItems] = useState(DEFAULT_ITEMS);
const handleToggleItem = (num) => {
return () => {
setItems(toggleArrayItem(items, num));
};
};
return {
items,
handleToggleItem,
};
}
๋ ํผ๋ฐ์ค
4 React Tips to Instantly Improve Your Code
Solid knowledge of React is one of the most valuable skills for a front-end developer. Many companies are constantly searching for React…
javascript.plainenglish.io
๊ธ ์์ ์ฌํญ์ ๋ ธ์ ํ์ด์ง์ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ๋ฐ์๋ฉ๋๋ค. ๋งํฌ๋ฅผ ์ฐธ๊ณ ํด ์ฃผ์ธ์
'๐ช Programming' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [JS] ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋ ์ต์ ํ ๊ธฐ๋ฒ ๋ชจ์ (23) | 2024.12.07 |
|---|---|
| [Algorithm] ์ฌ๋ผ์ด๋ฉ ์๋์ฐ Sliding Window ์๊ณ ๋ฆฌ์ฆ ํบ์๋ณด๊ธฐ (2) | 2024.11.11 |
| [Flutter] ํ๋ฌํฐ ๊ธฐ์ด ๋ด์ฉ ์ ๋ฆฌ - Part 2 (1) | 2024.10.13 |
| [Flutter] ํ๋ฌํฐ ๊ธฐ์ด ๋ด์ฉ ์ ๋ฆฌ - Part 1 (0) | 2024.10.05 |
| [TS] ํ์ ์คํฌ๋ฆฝํธ ๋ธ๋๋๋ ํ์ (0) | 2024.09.26 |
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote
๋ค๋ฅธ ๊ธ
-
[JS] ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋ ์ต์ ํ ๊ธฐ๋ฒ ๋ชจ์
[JS] ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋ ์ต์ ํ ๊ธฐ๋ฒ ๋ชจ์
2024.12.07 -
[Algorithm] ์ฌ๋ผ์ด๋ฉ ์๋์ฐ Sliding Window ์๊ณ ๋ฆฌ์ฆ ํบ์๋ณด๊ธฐ
[Algorithm] ์ฌ๋ผ์ด๋ฉ ์๋์ฐ Sliding Window ์๊ณ ๋ฆฌ์ฆ ํบ์๋ณด๊ธฐ
2024.11.11 -
[Flutter] ํ๋ฌํฐ ๊ธฐ์ด ๋ด์ฉ ์ ๋ฆฌ - Part 2
[Flutter] ํ๋ฌํฐ ๊ธฐ์ด ๋ด์ฉ ์ ๋ฆฌ - Part 2
2024.10.13 -
[Flutter] ํ๋ฌํฐ ๊ธฐ์ด ๋ด์ฉ ์ ๋ฆฌ - Part 1
[Flutter] ํ๋ฌํฐ ๊ธฐ์ด ๋ด์ฉ ์ ๋ฆฌ - Part 1
2024.10.05