【发布时间】:2021-06-28 20:04:00
【问题描述】:
构建可重用、可链接的过滤器组件最“React”的方式是什么?
假设我有一个输入数组:
[
{name: 'Generic t-shirt', size: 'xxl', available: 35},
{name: 'Generic t-shirt', size: 'md', available: 2},
{name: 'Generic t-shirt', size: 'sm', available: 5},
{name: 'Really awesome shirt', size: 'md', available: 0}
]
还有一个名称的关键字搜索、一个大小的下拉菜单和一个“售罄”布尔复选框来表示可用性。
现在,我在渲染循环中有过滤代码:
const [productsFilteredByFullText, setProductsFilteredByFullText] = useState;
const [productsFilteredBySize, setProductsFilteredBySize] = useState;
const [productsFilteredByAvailability, setProductsFilteredByAvailability] = useState;
const searchResults = useMemo(() => {
let filteredProducts = eventsFromAPI; // array of products as input
filteredProducts = filteredEvents.filter(product => fullTextFilter(product));
filteredProducts = filteredEvents.filter(product => sizeFilter(product));
filteredProducts = filteredEvents.filter(product => availabilityFilter(product));
return filteredProducts;
}, [productsFilteredByFullText, productsFilteredBySize, productsFilteredByAvailability]);
还有 JSX 内部的 UI:
<div>
// Fulltext search
<input
type="text"
placeholder="Keyword search"
value={searchTerm}
onChange={fullTextHandler}
/>
// Size dropdown
<Dropdown
options={allAvailableSizes}
onChange={sizeHandler}
/>
// Sold out checkbox
<input
name="soldout"
type="checkbox"
checked={productsFilteredByAvailability}
onChange={availabilityHandler}
/>
<h1>Results</h1>
{filteredProducts.map(item => (
<Product item={item} />
))}
</div>
这可行,但根本不是很可重用。假设我有另一个产品类别,围巾,它们都是一个尺寸,但我仍然希望能够重复使用过滤器组件和逻辑来获取名称和可用性。
有没有办法将过滤器逻辑和表示 JSX 模块化/组件化为单独的过滤器组件,并能够任意将它们链接在一起?像这样的伪代码:
<TShirtList>
<NameFilter/>
<SizeFilter/>
<AvailabilityFilter/>
</TShirtList>
<ScarfList>
<NameFilter/>
<AvailabilityFilter/>
</ScarfList>
<ServicesList>
<NameFilter/>
</ServicesList>
所以每个过滤器都是它自己的组件,可以插入到任何地方的任何产品数组中吗?就像 React 组件如何还提供其他组件可以使用的自己的逻辑/功能一样(产品数组输入,过滤后的产品数组 + JSX UI 输出,但可链接)。
这是思考这个问题的正确方法吗...?我对如何在架构上最好地构建它感到困惑。
【问题讨论】:
-
filter返回一个数组,因此您可以链接任何其他数组函数,例如另一个filter,然后最终是map,以将生成的过滤数据数组映射到 JSX。我可以想象在数据上使用reduce函数,使用一组过滤器函数可以使代码更加干燥和可重用。 -
这从数组操作的角度来看是可行的,但它并没有真正允许将过滤器逻辑和 UI 模块化到单独的组件中。例如要连续添加多个过滤器,您必须在渲染循环中单独编写过滤器逻辑,然后为 UI 添加 JSX 并手动将其绑定到逻辑中。有没有办法用UI+逻辑做一个JSX的“管道”?
-
您可以在父组件中保存一个过滤器(具有所有条件的对象),然后将设置器提供给“过滤子组件”(例如
<NameFilter onChange={(newFilterItem) => setFilter((oldFilter) => ({...oldFilter, yourCriteria: newFilterItem.yourCriteria || null })) } />)。让我知道我是否应该为此描述一个答案。
标签: arrays reactjs filter react-hooks react-component