고급 반응 패턴: 렌더 소품
19071 단어 webdevjavascripttutorialreact
꽤 오랫동안 React로 작업했다면 재사용 가능한 구성 요소를 작성하는 데 정통해야 합니다. 재사용 가능한 UI 구성 요소! 그러나 코드베이스가 확장됨에 따라 비즈니스 로직을 공유하고 싶지만 UI가 다를 수 있는 상황에 종종 직면하게 됩니다.
💡 이와 같은 상황은 일부 고급 패턴을 사용할 수 있는 완벽한 기회입니다. Render Props는 그러한 패턴 중 하나입니다.
🚀 렌더링 소품 패턴을 사용하는 일부 라이브러리에는 React Router, Downshift 및 Formik이 포함됩니다.
예부터 시작하겠습니다.
예를 들어 제품을 전시하는 온라인 상점을 구축하고 있습니다.
모든 제품 목록에 필요한 공통 비즈니스 논리가 있습니다.
🎨 그러나 목록이 렌더링되는 위치에 따라 UI도 다를 수 있습니다. 한 곳에서는 통계 또는 제품 이미지를 보여주고 싶고, 다른 곳에서는 제목만 보여주고 싶을 수도 있습니다.
🧠 먼저 렌더 소품 구성 요소의 기본 구조를 이해해 봅시다.
const Wrapper = ({ products, render }) => {
// do some stuff
const updatedProducts = someOperations(products)
// provide some helper funcs for data like sort func
const sort = () => {}
return render({ updatedProducts, sort })
}
👉 Render Props 구성 요소는 UI 구성 요소를 감싸는 래퍼일 뿐입니다. 위의 구성 요소는
products
및 render
두 개의 소품을 얻습니다. products
는 비즈니스 로직을 사용하여 수정해야 하는 데이터이고 render
는 이 수정된 데이터와 일부 다른 도우미 함수가 전달되는 함수입니다.🤔 그런데 이 구성 요소를 어떻게 사용합니까?
// import everything
const HomeScreenProducts = () => {
// assume you have this hook
const { products } = useData()
return (
<ProductsWrapper
products={products}
render={
({ updatedProducts, sort }) => updatedProducts.map(product => <ProductCard />)
}
/>
)
}
👉 우리의
HomeScreenProducts
구성 요소는 ProductsWrapper
를 사용하고 모든 비즈니스 로직을 처리하도록 합니다. UI는 여전히 호출 구성 요소에 의해 제어됩니다.내부
render
함수에서는 수정된 제품 데이터를 소비하고 이를 기반으로 UI를 렌더링합니다.😰 조금 복잡해 보입니다. 하지만 훨씬 더 깨끗한 API를 갖도록 단순화할 수 있습니다.
render
함수를 별도로 전달하는 대신 children
소품을 사용할 수 있습니다.업데이트 후 두 구성 요소는 다음과 같습니다.
const Wrapper = ({ products, children }) => {
// same stuff here
return children({ updatedProducts, sort })
}
const HomeScreenProducts = () => {
// same stuff here
return (
<ProductsWrapper products={products}>
{({ updatedProducts, sort }) => updatedProducts.map(product => <ProductCard />}
</ProductsWrapper>
)
}
👌 이게 훨씬 낫습니다.
children
소품은 이전에 사용했던 render
소품과 동일한 용도로 사용됩니다. 렌더 소품을 작성하는 이 방법이 더 일반적입니다.⚠️ 목록에
key
를 추가하는 것을 잊지 마세요.💪 이제 렌더링 소품 패턴을 이해했으므로 앞에서 언급한 작업을 완료할 수 있습니다.
import React from "react";
import { useAuth } from "./hooks/useAuth";
const ProductsWrapper = ({ products, children }) => {
const { isLoggedIn } = useAuth();
const [sortedProducts, setSortedProducts] = React.useState(products);
const sort = (order) => {
const reorderedProducts = [...products];
reorderedProducts.sort((a, b) => {
if (order === "desc") {
return b.price > a.price;
} else {
return a.price > b.price;
}
});
setSortedProducts(reorderedProducts);
};
const save = (productId) => {
if (isLoggedIn) {
// call API
console.log("Saving in DB... ", productId);
} else {
// save to local storage
console.log("Saving in local storage... ", productId);
}
};
const navigate = () => {
console.log("Navigating...");
};
return children({ sortedProducts, sort, save, navigate });
};
export default ProductsWrapper;
ProductsWrapper
구성 요소를 확장하고 여기에 필요한 모든 기능을 추가합니다. children
를 함수로 호출하고 데이터 및 헬퍼 함수를 전달합니다.import ProductsWrapper from "./ProductsWrapper";
const products = [
{ id: 1, name: "Coffee", price: 2 },
{ id: 2, name: "Choclates", price: 3 },
{ id: 3, name: "Milk", price: 5 },
{ id: 4, name: "Eggs", price: 4 },
{ id: 5, name: "Bread", price: 1 }
];
export default function App() {
return (
<div className="App">
<ProductsWrapper products={products}>
{({ sortedProducts, sort, save, navigate }) => (
<>
<div className="flex">
<button onClick={() => sort("desc")}>Price: High to Low</button>
<button onClick={() => sort("asc")}>Price: Low to High</button>
</div>
{sortedProducts.map((product) => (
<div className="product" key={product.id}>
<span onClick={() => navigate(product.id)}>
{product.name} - ${product.price}
</span>
<button className="save-btn" onClick={() => save(product.id)}>
save
</button>
</div>
))}
</>
)}
</ProductsWrapper>
</div>
);
}
✅ 우리의 UI 구성 요소는
ProductsWrapper
를 사용하고 UI를 관리합니다. 보시다시피 자유롭게 UI를 수정하거나 이것과 완전히 다르게 보이는 다른 UI 구성 요소를 만들 수 있습니다. 우리의 비즈니스 로직은 한 곳에 있습니다.예제를 가지고 놀고 싶다면 codesandbox에서 사용할 수 있습니다: https://codesandbox.io/s/render-props-example-6190fb
그게 다야! 👋
🤙 도움이 되었다면 공유하고 에서 저와 연결해 보세요.
Reference
이 문제에 관하여(고급 반응 패턴: 렌더 소품), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/thesanjeevsharma/advance-react-patterns-render-props-3hjj텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)