Use Composition to get rid of props drilling in React
(2 min read)
Passing props using props drilling
type TProduct = {
id: number;
name: string;
price: number;
quantity: number;
};
type TProps = {
product: TProduct;
};
function Order({ product }: TProps) {
return <div>Order Quantity: {product.quantity} </div>;
}
function Payment({ product }: TProps) {
return <div>Payment Price: {product.price}</div>;
}
function ProductDetail({ product }: TProps) {
return (
<div>
<div>Product Id: {product.id}</div>
<div>Product Name: {product.name}</div>
<div>
<Order product={product} />
</div>
<div>
<Payment product={product} />
</div>
</div>
);
}
function ProductComponent({ product }: TProps) {
return (
<div>
<h3>Product Component</h3>
<ProductDetail product={product} />
</div>
);
}
function fetchProduct() {
const product: TProduct = { id: 1, name: 'Laptop', quantity: 5, price: 1000 };
return product;
}
export default function PropDrillingPage() {
const product = fetchProduct();
return (
<div>
<h2>Props Drilling</h2>
<ProductComponent product={product} />
</div>
);
}
Using Composition
import React from 'react';
type TProduct = {
id: number;
name: string;
price: number;
quantity: number;
};
type TProps = {
product: TProduct;
};
function Order({ product }: TProps) {
return <div>Order Quantity: {product.quantity} </div>;
}
function Payment({ product }: TProps) {
return <div>Payment Price: {product.price}</div>;
}
function ProductDetail({ product }: TProps) {
return (
<div>
<div>Product Id: {product.id}</div>
<div>Product Name: {product.name}</div>
</div>
);
}
function ProductComponent({ children }: { children: React.ReactNode }) {
return <div>{children}</div>;
}
ProductComponent.displayName = 'Product';
ProductDetail.displayName = 'Product.Detail';
Order.displayName = 'Product.Order';
Payment.displayName = 'Product.Payment';
const Product = Object.assign(ProductComponent, {
Detail: ProductDetail,
Order: Order,
Payment: Payment,
});
function fetchProduct() {
const product: TProduct = { id: 1, name: 'Laptop', quantity: 5, price: 1000 };
return product;
}
export default function PropDrillingPage() {
const product = fetchProduct();
return (
<div>
<h2>Composition</h2>
<Product>
<Product.Detail product={product} />
<Product.Order product={product} />
<Product.Payment product={product} />
</Product>
</div>
);
}