[React] ๋ฆฌ์กํธ Render Props ํจํด 2๊ฐ์ง ์ฌ์ฉ ๋ฐฉ๋ฒ
children
Prop์ ์ด์ฉํด ์ปดํฌ๋ํธ ํฉ์ฑ(component composition) ํํ๋ก ์์ฑํ๋ฉด ๋ถ๋ชจ ์ปดํฌ๋ํธ๋ฅผ ์์ ํ์ง ์๊ณ ๋ ์์ ์ปดํฌ๋ํธ๋ฅผ ์์ ๋กญ๊ฒ ์ถ๊ฐํด์ ์ฌ์ฉํ ์ ์๋ค.
์ผ๋ฐ์ ์ผ๋ก ๋ฐ์ดํฐ(์ํ) ๊ณต์ ๋ ์ํ ๋์ด์ฌ๋ฆฌ๊ธฐ
๋ฐฉ๋ฒ์ด ๊ฐ์ฅ ๊ฐ๋จํ์ง๋ง ์ต์์ ์ปดํฌ๋ํธ๊ฐ ๋ฐ์ดํฐ(์ํ)์ ๋ชจ๋ ํ์ ์ปดํฌ๋ํธ๋ฅผ ๊ฐ๊ณ ์์ผ๋ฉด ํด๋น ์ํ์ ๊ด๋ จ ์๋ ๋ชจ๋ ํ์ ์ปดํฌ๋ํธ๋ ๋ ๋๋ง์ ์ํฅ์ ์ฃผ๋ ๋จ์ ์ด ์๋ค(์ํ ๋์ด์ฌ๋ฆฌ๊ธฐ๋ก ๋ถ๋ชจ ์ปดํฌ๋ํธ ์ํ๊ฐ ๋ณ๊ฒฝ๋ผ์ ์
๋ฐ์ดํธํ๋ฉด ํ์ ์ปดํฌ๋ํธ๋ ๋ค์ ๋ ๋๋ง ํ๋ฏ๋ก).
์ด๋ Render Props ํจํด์ ํ์ฉํ ์ ์๋ค. ์ด๋ค ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ ์ง์ ๋ํ ๋ก์ง์ ์์ ์ปดํฌ๋ํธ๊ฐ ๊ฒฐ์ ํ๊ณ , ํ์ ์ปดํฌ๋ํธ๋ ์์ ์ด ๊ด๋ฆฌํ๋ ์ํ๋ฅผ ์ธ์๋ก ๋ฐ์ render
(ํน์ children
) Prop์ ํธ์ถํ์ฌ ๋ฐ์ดํฐ๋ ๋ก์ง์ ๋ค๋ฅธ ์ปดํฌ๋ํธ์๊ฒ ๊ณต์ ํ๋ ๋ฐฉ์์ด๋ค.
์ํ ๋์ด์ฌ๋ฆฌ๊ธฐ ์์. ์ ๋ ฅ ์ํ๋ App์ด ๊ฐ์ง๊ณ ํ์ ์ปดํฌ๋ํธ์ธ Input์์ ์ํ ๋์ด์ฌ๋ฆฌ๊ธฐ๋ก ์ ๋ ฅ ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ฉด ๋ค๋ฅธ ํ์ ์ปดํฌ๋ํธ๋ ๋ชจ๋ ๋ค์ ๋ ๋๋งํ๋ค.
function Input({ value, handleChange }) {
return <input value={value} onChange={(e) => handleChange(e.target.value)} />;
}
function App() {
const [value, setValue] = useState(''); // value๊ฐ ๋ณ๊ฒฝ๋๋ฉด ๋ชจ๋ ํ์ ์ปดํฌ๋ํธ๋ ๋ค์ ๋ ๋๋ง
return (
<div className="App">
<h1>Temperature Converter</h1>
<Input value={value} handleChange={setValue} />
<Kelvin value={value} />
<Fahreheit value={value} />
</div>
);
}
Render Props ํจํด ์์. App ์ปดํฌ๋ํธ ์์์ผ๋ก Input๋ง ๊ฐ์ง๊ณ , Input ์์์ ์ด๋ค ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ ์ง๋ App ์ปดํฌ๋ํธ๊ฐ ๊ฒฐ์ . ์ ๋ ฅ ์ํ๋ Input์ด ๊ด๋ฆฌํ๊ณ , Input ๋ด๋ถ ์ํ๋ Render Prop ํํ๋ก ๋ค์ Input ์์์ผ๋ก ์ ๋ฌ.
function App() {
return (
<div className="App">
<h1>Temperature Converter</h1>
<input
render={(value) => (
<>
<Kelvin value={value} />
<Fahrenheit value={value} />
</>
)}
/>
</div>
);
}
function Input({ render }) {
const [value, setValue] = useState('');
return (
<>
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="Temp in โ"
/>
{render(value)} {/* value๋ Kelvin, Fahrenheit ์ปดํฌ๋ํธ๋ก ์ ๋ฌ๋จ */}
</>
);
}
๋ฐฉ๋ฒ 1 — Children Prop
children Props ํํ๋ก ์ฌ์ฉ
export default function CheckoutMobile({ orders, initialOrderIds }): Props {
const {
// ...
getTableProps, // Native Props ๋
ธ์ถ๋์ Props Getters ๋ชฉ๋ก์ ์ ๊ณตํ๋ Props Getters ํจํด
} = useCheckout({ initialOrderIds, orders });
const { PaymentInfoModal, handlePaymentInfoModal } = usePaymentInfoModal();
return (
<div className="flex flex-col gap-2">
{renderList.map(([date, orders]) => (
<CheckoutTableContainer
key={date}
{...getTableProps(date, orders)} // useCheckout ํ
์ด ๋ฐํํ Props ์ ๋ฌ
>
{(tableBodyProps) => (
<>
<CheckoutTHeader />
<CheckoutTBody
{...tableBodyProps}
handlePaymentInfoModal={handlePaymentInfoModal}
/>
</>
)}
</CheckoutTableContainer>
))}
</div>
);
}
interface CheckoutTableContainerProps extends CheckoutTableData {
tableClasses?: string;
children: <T extends CheckoutTBodyData>(tableBodyProps: T) => JSX.Element;
}
export default function CheckoutTableContainer({
// ...getCheckoutTableContainerProps ํจ์๋ฅผ ํธ์ถ์ ์ ๋ฌ๋ฐ์ Props ์๋ต
children,
...tableBodyProps // ๋๋จธ์ง Props๋ ํ
์ด๋ธ Body์ ์ฌ์ฉ
}: CheckoutTableContainerProps) {
return (
<section className="bg-white py-4 max-w-[767px]">
<div className="flex gap-3 py-4 px-4">{/* ... */}</div>
<table className={tableClasses}>{children(tableBodyProps)}</table>
</section>
);
}
๋ฐฉ๋ฒ 2 — Render Prop
render Prop ํํ๋ก ์ฌ์ฉ
๊ผญ render
Prop ์ด๋ฆ์ ์ฌ์ฉํ์ง ์์๋ ๋๋ค. renderFirstComponent
๋ฑ์ ์ด๋ฆ๋ ๊ฐ๋ฅ.
export default function CheckoutMobile({ orders, initialOrderIds }: Props) {
const {
// ...
getTableProps, // Native Props ๋
ธ์ถ๋์ Props Getters ๋ชฉ๋ก์ ์ ๊ณตํ๋ Props Getters ํจํด
} = useCheckout({ initialOrderIds, orders });
const { PaymentInfoModal, handlePaymentInfoModal } = usePaymentInfoModal();
return (
<div className="flex flex-col gap-2">
{renderList.map(([date, orders]) => (
<CheckoutTableContainer
{...getTableProps(date, orders)} // useCheckout ํ
์ด ๋ฐํํ Props ์ ๋ฌ
key={date}
render={(tableBodyProps) => (
<>
<CheckoutTHeader />
<CheckoutTBody
{...tableBodyProps}
handlePaymentInfoModal={handlePaymentInfoModal}
/>
</>
)}
/>
))}
</div>
);
}
interface CheckoutTableContainerProps extends CheckoutTableData {
tableClasses?: string;
render: <T extends CheckoutTBodyData>(tableBodyProps: T) => JSX.Element;
}
export default function CheckoutTableContainer({
// ...getCheckoutTableContainerProps ํจ์๋ฅผ ํธ์ถ์ ์ ๋ฌ๋ฐ์ Props ์๋ต
render,
...tableBodyProps // ๋๋จธ์ง Props๋ ํ
์ด๋ธ Body์ ์ฌ์ฉ
}: CheckoutTableContainerProps) {
return (
<section className="bg-white py-4 max-w-[767px]">
<div className="flex gap-3 py-4 px-4">{/* ... */}</div>
<table className={tableClasses}>{render(tableBodyProps)}</table>
</section>
);
}
๋ ํผ๋ฐ์ค
๊ธ ์์ ์ฌํญ์ ๋ ธ์ ํ์ด์ง์ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ๋ฐ์๋ฉ๋๋ค. ๋งํฌ๋ฅผ ์ฐธ๊ณ ํด ์ฃผ์ธ์
'๐ช Programming' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote
๋ค๋ฅธ ๊ธ
-
[React] falsy ๊ฐ์ ์ฌ์ฉํ ๋ฆฌ์กํธ ์กฐ๊ฑด๋ถ ๋ ๋๋ง์ ์ฃผ์ํ ์
[React] falsy ๊ฐ์ ์ฌ์ฉํ ๋ฆฌ์กํธ ์กฐ๊ฑด๋ถ ๋ ๋๋ง์ ์ฃผ์ํ ์
2024.05.11 -
[JS] ํน์ ์์ ์์น๋ก ์คํฌ๋กค ์ด๋ํ๊ธฐ - scrollIntoView
[JS] ํน์ ์์ ์์น๋ก ์คํฌ๋กค ์ด๋ํ๊ธฐ - scrollIntoView
2024.05.11 -
[TS] ํ์ ์คํฌ๋ฆฝํธ ํ์ ๊ฐ๋ is / asserts ํค์๋ ์ฐจ์ด์
[TS] ํ์ ์คํฌ๋ฆฝํธ ํ์ ๊ฐ๋ is / asserts ํค์๋ ์ฐจ์ด์
2024.05.10 -
[DevTools] ๊ฐ๋ฐ์ ์นํ์ ์ธ ํฐ๋ฏธ๋ LS — PLS
[DevTools] ๊ฐ๋ฐ์ ์นํ์ ์ธ ํฐ๋ฏธ๋ LS — PLS
2024.05.10