๐ ๋ชฉ๋ก
- HOC ๋?
- ๊ฐ๋จํ HOC ๊ตฌํ
- JSON Placeholder ๋ฐ์ดํฐ๋ก withLoader ๋ง๋ค๊ธฐ
- HOC์ ์ฅ์ ๊ณผ ๋จ์
๐ HOC ๋?
High Order Component๋ ๊ณตํต ๋ก์ง์ ์ฌ์ฌ์ฉ ํด์ ์ฌ์ฉํ๊ฒ ๋ ๋ง๋ค์ด ์ค๋๋ค. ๋ง์น mixin๊ณผ ๊ฐ์ด์. ํ์ง๋ง ์ด๋ค ์ปดํฌ๋ํธ๋ฅผ ํ๋ฒ ๊ฐ์ธ์ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค๊ฒ ํฉ๋๋ค. ๊ทธ๋ผ ํ๋ฒ ์ด๋ค ๋ ์์ธ์ง ๋ณผ๊น์?
๐ ๊ฐ๋จํ HOC ๊ตฌํ
๋จผ์ ์ด๋ฐ withStyle ํจ์๋ฅผ ํ๋ฒ ์ ์ํด๋ณผ๊ฒ์.
const withStyle = (Component) => {
return props => {
return <Component style={{ color: 'red', border: 'solid 1px blue', }} {...props} />
}
}
๊ทธ๋ฆฌ๊ณ ๋ฒํผ๊ณผ Text๋ฅผ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค.
import withStyle from "./hoc/withStyles";
const Button = ({ style, children }) => <button style={style}>{ children }</button>;
const StyledButton = withStyle(Button);
export default StyledButton;
import withStyle from "./hoc/withStyles";
const Text = ({ style, children }) => <p style={style}>{ children }</p>
const StyledText = withStyle(Text);
export default StyledText;
์ด์ฒ๋ผ ํ๋ฒ ๊ฐ์ธ์ฃผ๋ ํํ๋ก ๋ก์ง์ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
๐ JSON Placehodler ๋ฐ์ดํฐ๋ก withLoader ๋ง๋ค๊ธฐ
๊ทธ๋ ๋ค๋ฉด ์ด๋ฒ์ ํ๋ฒ data fetch์ ๊ด๋ จํ ์์ด๋ฅผ ๋ง๋ค์ด ๋ณผ๊น์?
์ฌ๊ธฐ์๋ JSONPlaceholder
๋ฅผ ์ฌ์ฉํ์์ต๋๋ค.
๋จผ์ ApiService ๊ฐ์ฒด๋ฅผ ํ๋ ๋ง๋ค์ด ์ค๊ฒ์.
import axios from 'axios';
const ApiService = axios.create({
baseURL: 'https://jsonplaceholder.typicode.com/',
timeout: 1000,
});
ApiService.interceptors.response.use(
(response) => response.data,
(error) => Promise.reject(error)
);
export default ApiService;
๊ทธ๋ฆฌ๊ณ ์ด๊ฑธ withLoader์ ์ ์ฉ์์ผ ๋ณด๊ฒ ์ต๋๋ค.
import { useState, useEffect, useCallback } from 'react';
import ApiService from '../../services';
const withLoader = (Component, url) => {
return (props) => {
const [data, setData] = useState();
const [loading, setLoading] = useState(false);
const fetchData = useCallback(async () => {
setLoading(true);
setData(await ApiService.get(url));
setLoading(false);
}, []);
useEffect(() => {
fetchData();
} , [fetchData]);
if (loading) return <div style={{ fontSize: '200px' }}>Loading...</div>
else return <Component {...props} data={data} fetchData={fetchData} />
}
}
export default withLoader;
์ด์ ์ด๊ฑธ Todo์ ํ๋ฒ ์ฐ๊ฒฐ์ ํด๋ณผ๊น์?
import { useMemo } from "react";
import withLoader from "./hoc/withLoader";
const Todo = ({ todo }) => {
const title = useMemo(() => todo?.title ?? "", [todo]);
const completed = useMemo(() => todo?.completed ?? false, [todo]);
return (
<li>
<span style={{ textDecoration: "bold", marginRight: "4px" }}>
{title}
</span>
<input type="checkbox" checked={completed} onChange={() => {}} />
</li>
);
};
const Todos = ({ data, fetchData }) => {
return (
<section style={{ marginTop: '20px' }}>
<button onClick={fetchData}>Refecth Data</button>
<ul>
{data?.map((todo) => (
<Todo key={todo.id} todo={todo} />
))}
</ul>
</section>
);
};
export default withLoader(Todos, "todos");
๐ HOC์ ์ฅ์ ๊ณผ ๋จ์
์ฅ์
- ๋ก์ง ์ฌ์ฌ์ฉ์ ํ ์ ์๋ค.
๋จ์
- HOC๋ ์ค์ฒฉ์ด ๊ฐ๋ฅํ๋ฐ depth๊ฐ ๊น์ด์ง๋ฉด ์ฐพ์๋ค๋๊ธฐ๊ฐ ํ๋ค๋ค.
'Design Pattern' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Render Props Pattern (with React) (0) | 2022.01.21 |
---|---|
Mixin Pattern (0) | 2022.01.20 |
Mediator Pattern (0) | 2020.10.23 |
Observer Pattern (0) | 2020.10.19 |
Module Pattern (0) | 2020.10.07 |