如何使用布局组件并使用 React redux 工具包更改带有 ID 的数据
How to use a layout component and change the data with the ID using react redux toolkit
我正在尝试为我在多个页面上使用的布局制作一个组件,并希望根据页面更改数据。
我设置了一个商店并立即获取每个页面的数据,但是有 4 个页面具有相同的布局,我想使布局成为它自己的组件。我不知道怎么做,所以它会根据categoryID改变。
下面是我的代码的一小部分。
const Books = () => {
const products = useSelector(state => state.products)
return (
<>
<SideMenu/>
{products.map(product => (
<div key={product.categoryId + product.description} >
{(product.sortOrder === 0 && product.categoryId === 2 )? <>
<img className="img-fluid"
src={product.imagePath}
alt="book"
id="book"
/>
</>
:<> </>}
<div className="mainBack">
{(product.sortOrder === 0) && (product.categoryId === 2) && (product.description !== null) ? <>
<div className="row">
<div className=" col"
id="description" >
{product.description}
</div>
</div>
</>
: <> </>}
</>
export default Books;
我希望有一个 Layout.js 组件,其中包含所有 HTML 和带有 ID 变量的数据,我可以在另一个组件中更改。
看起来您正在尝试做的是过滤产品,以便只显示带有 (product.sortOrder === 0) && (product.categoryId === 2)
的产品。在不同的页面上,您想使用不同的过滤器执行相同的操作。您可以使用 selector 函数 select 仅 select 您想要的产品,而不是 select 使用 useSelector
的所有产品。然后我们可以从 JSX 中删除那些条件检查。
让我们让它变得非常灵活。首先让我们创建一个组件,它接受一个道具 product
,它是一个单一的产品,并以类别页面的格式呈现它,可能是某种“tile”。
const ProductTile = ({ product }) => {
return (
<div>
<img className="img-fluid" src={product.imagePath} alt="book" id="book" />
<div className="mainBack">
{
// is this check necessary? Do some products really have a `null` description?
product.description !== null && (
<div className="row">
<div className=" col" id="description">
{product.description}
</div>
</div>
)
}
</div>
</div>
);
};
然后让我们制作一个组件,该组件采用产品数组 products
并呈现包含这些产品的产品列表页面。这是您包含 <SideMenu/>
等布局元素的地方。
const ProductListingPage = ({ products }) => {
return (
<div>
<SideMenu />
{products.map((product) => (
<ProductTile
product={product}
// I hate this key! do you have a `product.id` that you can use?
// needs a fallback if product.description might be null
// but this is a problem because you will have non-unique keys
key={product.categoryId + (product.description || "")}
/>
))}
</div>
);
};
这两个是所谓的“展示”组件,因为它们所做的一切都是从道具中获取数据并展示它。他们没有任何状态或调用任何钩子。
所以现在我们要创建一个包含逻辑的“容器”组件。该组件将 categoryId
作为道具。它将 select 该类别中的所有产品,并根据它们的 sortOrder
对它们进行排序。然后它将这些产品传递给处理渲染的 ProductListingPage
。
大部分逻辑在selector中,我们可以将其定义为一个单独的函数。我正在使用带有自定义比较器函数的 lodash sortBy
function because it is easy to write and understand compared to using Array.sort。
import React from "react";
import { useSelector } from "react-redux";
import sortBy from "lodash/sortBy";
// double arrow function takes a categoryId and returns a selector function for that category
const selectCategoryProducts = (categoryId) =>
(state) => {
// filter to only those that match the categoryId
const catProducts = state.products.filter(
(product) => product.categoryId === categoryId
);
// sort them by sortOrder using lodash sortBy
return sortBy(catProducts, "sortOrder");
};
const CategoryProductsPage = ({categoryId}) => {
const products = useSelector(selectCategoryProducts(categoryId));
return (
<ProductListingPage products={products}/>
)
}
将 ProductListingPage
作为独立于 CategoryProductsPage
的组件,这意味着您可以使用不同的 select 产品创建产品列表页面,例如最新产品(不考虑类别)、特色产品等
我正在尝试为我在多个页面上使用的布局制作一个组件,并希望根据页面更改数据。
我设置了一个商店并立即获取每个页面的数据,但是有 4 个页面具有相同的布局,我想使布局成为它自己的组件。我不知道怎么做,所以它会根据categoryID改变。
下面是我的代码的一小部分。
const Books = () => {
const products = useSelector(state => state.products)
return (
<>
<SideMenu/>
{products.map(product => (
<div key={product.categoryId + product.description} >
{(product.sortOrder === 0 && product.categoryId === 2 )? <>
<img className="img-fluid"
src={product.imagePath}
alt="book"
id="book"
/>
</>
:<> </>}
<div className="mainBack">
{(product.sortOrder === 0) && (product.categoryId === 2) && (product.description !== null) ? <>
<div className="row">
<div className=" col"
id="description" >
{product.description}
</div>
</div>
</>
: <> </>}
</>
export default Books;
我希望有一个 Layout.js 组件,其中包含所有 HTML 和带有 ID 变量的数据,我可以在另一个组件中更改。
看起来您正在尝试做的是过滤产品,以便只显示带有 (product.sortOrder === 0) && (product.categoryId === 2)
的产品。在不同的页面上,您想使用不同的过滤器执行相同的操作。您可以使用 selector 函数 select 仅 select 您想要的产品,而不是 select 使用 useSelector
的所有产品。然后我们可以从 JSX 中删除那些条件检查。
让我们让它变得非常灵活。首先让我们创建一个组件,它接受一个道具 product
,它是一个单一的产品,并以类别页面的格式呈现它,可能是某种“tile”。
const ProductTile = ({ product }) => {
return (
<div>
<img className="img-fluid" src={product.imagePath} alt="book" id="book" />
<div className="mainBack">
{
// is this check necessary? Do some products really have a `null` description?
product.description !== null && (
<div className="row">
<div className=" col" id="description">
{product.description}
</div>
</div>
)
}
</div>
</div>
);
};
然后让我们制作一个组件,该组件采用产品数组 products
并呈现包含这些产品的产品列表页面。这是您包含 <SideMenu/>
等布局元素的地方。
const ProductListingPage = ({ products }) => {
return (
<div>
<SideMenu />
{products.map((product) => (
<ProductTile
product={product}
// I hate this key! do you have a `product.id` that you can use?
// needs a fallback if product.description might be null
// but this is a problem because you will have non-unique keys
key={product.categoryId + (product.description || "")}
/>
))}
</div>
);
};
这两个是所谓的“展示”组件,因为它们所做的一切都是从道具中获取数据并展示它。他们没有任何状态或调用任何钩子。
所以现在我们要创建一个包含逻辑的“容器”组件。该组件将 categoryId
作为道具。它将 select 该类别中的所有产品,并根据它们的 sortOrder
对它们进行排序。然后它将这些产品传递给处理渲染的 ProductListingPage
。
大部分逻辑在selector中,我们可以将其定义为一个单独的函数。我正在使用带有自定义比较器函数的 lodash sortBy
function because it is easy to write and understand compared to using Array.sort。
import React from "react";
import { useSelector } from "react-redux";
import sortBy from "lodash/sortBy";
// double arrow function takes a categoryId and returns a selector function for that category
const selectCategoryProducts = (categoryId) =>
(state) => {
// filter to only those that match the categoryId
const catProducts = state.products.filter(
(product) => product.categoryId === categoryId
);
// sort them by sortOrder using lodash sortBy
return sortBy(catProducts, "sortOrder");
};
const CategoryProductsPage = ({categoryId}) => {
const products = useSelector(selectCategoryProducts(categoryId));
return (
<ProductListingPage products={products}/>
)
}
将 ProductListingPage
作为独立于 CategoryProductsPage
的组件,这意味着您可以使用不同的 select 产品创建产品列表页面,例如最新产品(不考虑类别)、特色产品等