견고한 React 지식은 프론트엔드 개발자에게 가장 가치있는 기술 중 하나입니다. 많은 회사들은 끊임없이 리액트 개발자들을 찾고있으며 그들에게 더 많은 돈을 지불하려 합니다. 그것이 개발자로서 끊임없이 발전해야 하는 중요한 이유이며, 매우보람 있는 노력입니다.
당신의 여정을 돕기 위해, 더 나은 리액트 코드를 작성하는데 유용했던 4가지 팁을 공유하려 합니다. 새롭고 유용한 것을 발견하길 바랍니다. 바로 시작하겠습니다!
차례
- handler 에서 함수 반환하기
- 책임 분리하기
- 조건문 대신에 객체 맵 사용하기
- 독립 변수를 React 라이프 사이클 외부에 두기
handler 에서 함수 반환하기
만약 함수형 프로그래밍이 친숙하다면, 무엇을 말하려고 하는지 알 것입니다. 흔히 "currying" 이라고도 합니다. 우리는 미리 함수의 매개변수를 설정할 수 있습니다.
하단의 코드는 비슷한 코드가 반복되는 문제가 분명히 있습니다. 이 기술이 우리에게 도움될 것입니다.
문제
export default function App() {
const [user, setUser] = useState({
name: "",
surname: "",
address: ""
});
// First handler
const handleNameChange = (e) => {
setUser((prev) => ({
...prev,
name: e.target.value
}));
};
// Second handler!
const handleSurnameChange = (e) => {
setUser((prev) => ({
...prev,
surname: e.target.value
}));
};
// Third handler!!!
const handleAddressChange = (e) => {
setUser((prev) => ({
...prev,
address: e.target.value
}));
};
// 만약 input이 하나 더 필요하다면? 그 input 때문에 또 다른 handler를 생성해야 할까요?
return (
<>
<input value={user.name} onChange={handleNameChange} />
<input value={user.surname} onChange={handleSurnameChange} />
<input value={user.address} onChange={handleAddressChange} />
</>
);
}
해결책
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)}
</>
);
}
5 React useState Mistakes That Will Get You Fired
5 Common React useState mistakes and how to avoid them
javascript.plainenglish.io
책임 분리하기
"God" 컴포넌트를 만드는 것은 개발자들이 흔히 저지르는 실수입니다. "God" 이라 불리는 이유는 이해와 유지보수를 어렵게 하는 많은 줄의 코드를 포함하고 있기 때문입니다. 컴포넌트들을 독립적인 하위 모듈의 세트로 만들어 분리하는 것을 강력히 추천합니다.
대표적인 구조는 다음과 같습니다.
- UI module, 오로지 보여지는 화면만 담당합니다.
- Logic/Model module, 오직 비즈니스 로직만 포함하고 있습니다. 예를 하나 들자면, 커스텀 훅과 같은 것들입니다.
- Lip module, 컴포넌트에 필요한 모든 유틸리티를 포함합니다.
이 개념을 설명을 돕기 위해 작은 데모를 예로 들어보겠습니다.
export function ListComponent() {
// Our local state
const [list, setList] = useState([]);
// Handler to load data from the server
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!" });
}
};
// We want to fetch only on mount
useEffect(() => {
fetchList();
}, []);
// Handler responsible for deleting items
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!" });
}
};
};
// Here we just render our data items
return (
<div className="list-component">
{list.map(({ id, name }) => (
<div key={id} className="list-component__item>">
{/* We want to trim long name with ellipsis */}
{name.slice(0, 30) + (name.length > 30 ? "..." : "")}
<div onClick={handleDeleteItem(id)} className="list-component__icon">
<DeleteIcon />
</div>
</div>
))}
</div>
);
}
우리는 모델과 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.lenght > 30 ? '...' : '')
}
이제 이 비즈니스 로직을 실행해야 합니다. 간단하게 우리가 필요한 커스텀 훅을 리턴해볼 것입니다.
export function useList() {
const [list, setList] = useState([]);
const handleDeleteItem = useCallback((id) => {
return () => {
deleteListItem(id, () => {
setList((prev) => prev.filter((x) => x.id !== id));
})
};
}, []);
useEffect(() => {
getList(setList);
}, []);
return useMemo(
() => ({
list,
handleDeleteItem
}),
[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>
);
}
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>
);
}
6 JavaScript Tips To Instantly Improve Your Code
Easy and Effective tips to make your JavaScript code better
javascript.plainenglish.io
조건문 대신에 객체 맵 사용하기
만약에 변수에 의존하는 다양한 요소를 보여주는 것이 필요하다면, 이 팁을 시행하면 됩니다. 쉬운 전략을 사용하는 것은 컴포넌트를 더 명확하고 코드 이해를 단순하게 만듭니다. 또한 기능을 확장하는 것이 덜 힘들 것입니다.
🌟 프론트엔드에게 필수이므로 잊지마세요!
문제
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>
)
}
해결책
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>
)
}
Frontend Architectures: “Classic” Approach (No Architecture)
Learn the Pros and Cons of the Most Common Frontend Architecture
javascript.plainenglish.io
독립 변수를 React 라이프 사이클 외부에 두기
이 아이디어는 리액트 컴포넌트의 라이프사이클 메서드가 필요하지 않은 로직을 그 컴포넌트에서 분리하는 것입니다. 이것은 독립적으로 만듬으로써 코드 명료성을 더욱 향상시켜줍니다. 따라서, 컴포넌트를 읽고 이해하기 더욱 쉬워집니다.
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,
}
}
해결책
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,
}
}
Frontend Architectures: “Simple Modular” Approach
Understand the Pros and Cons of the Modular Frontend Architecture
javascript.plainenglish.io
읽어주셔서 감사합니다.
출처 - https://javascript.plainenglish.io/4-react-tips-to-instantly-improve-your-code-7456e028cfa3