React hooks 在使用它作为 render-props 模式的替代品时不涵盖哪些用例?有什么实际例子吗?
我有一个包含三个列表的应用程序,其想法是创建一个通用组件以在我的应用程序中添加虚拟化。传递不同行样式/类和元素的能力是必须的。
我有两个实现,这两个实现有什么问题吗?你会选择哪一个?为什么?
列表 1 和列表 2 使用相同的方法,只是为了说明目的,我们有 2。列表 3 被简化为使用钩子,行在钩子选项中传递。 Components/List 和 hooks/useVirtalizer.jsx 使用方法 1(我知道我不能使事情复杂化并仅将逻辑保留在 List.jsx 中,但假设我有更多逻辑,我也将其拆分为一个钩子) hooks/useVirtualizerAllHooks.jsx 使用方法 2。
src/
├── App.jsx
├── components/
│ └── List.jsx
├── hooks/
│ ├── useVirtualizer.jsx
│ └── useVirtualizerAllHooks.jsx
└── data.js
import React from 'react';
import List from './components/List.jsx';
import useVirtualizerAllHooks from './hooks/useVirtualizerAllHooks.jsx';
import { DATA1, DATA2 } from './data.js';
export function App(props) {
const ListWrapper = useVirtualizerAllHooks({
row: (item) => {
return (
<li key={DATA1[item.index].id}>
<h1>{DATA1[item.index].name}</h1>
</li>
);
},
items: DATA1,
});
return (
<div className="App">
<p>List One</p>
<List items={DATA1}>
{(item) => (
<li key={DATA1[item.index].id}>
<p>{DATA1[item.index].name}</p>
</li>
)}
</List>
<p>List Two (Different styles & functionality)</p>
<List items={DATA2}>
{(item) => (
<li key={DATA2[item.index].id}>
<p>{DATA2[item.index].name}</p>
<button>dumdum</button>
</li>
)}
</List>
<p>List Three (All Hooks)</p>
<ListWrapper />
</div>
);
}
列表
import useVirtualizer from '../hooks/useVirtualizer.jsx';
export default function List(props) {
const { children, items } = props;
const { rows, parentRefInit } = useVirtualizer({ items });
return (
<ul ref={parentRefInit} style={{ height: 150, overflowY: 'auto' }}>
{rows.map((item) => children(item))}
</ul>
);
}
数据
export const DATA1 = Array.from({ length: 50 }, (v, i) => ({
id: i + 1,
name: `fake data ${i + 1}`
}));
export const DATA2 = Array.from({ length: 50 }, (v, i) => ({
id: i + 1,
name: `fake data2 ${i + 1}`
}));
使用虚拟化器
import { useWindowVirtualizer } from '@tanstack/react-virtual'
import { useCallback, useRef } from 'react'
export default function useVirtualizer({ items }) {
const parentRef = useRef(null)
const parentRefInit = useCallback((node) => {
if (node !== null) {
parentRef.current = node
}
}, [])
const virtualizer = useWindowVirtualizer({
count: items.length,
estimateSize: () => 50,
overscan: 5,
scrollMargin: parentRef.current?.offsetTop ?? 0,
})
return { rows: virtualizer.getVirtualItems(), parentRefInit }
}
使用VirtualizerAllHooks
import { useWindowVirtualizer } from '@tanstack/react-virtual'
import { useCallback, useRef } from 'react'
export default function useVirtualizer({ row, items }) {
const parentRef = useRef(null)
const parentRefInit = useCallback((node) => {
if (node !== null) {
parentRef.current = node
}
}, [])
const virtualizer = useWindowVirtualizer({
count: items.length,
estimateSize: () => 50,
overscan: 5,
scrollMargin: parentRef.current?.offsetTop ?? 0,
})
const List = () => {
if (virtualizer.getVirtualItems().length <= 0) return
return (
<ul ref={parentRefInit} style={{ height: 150, overflowY: 'auto' }}>
{virtualizer.getVirtualItems().map((item) => row(item))}
</ul>
)
}
return List
}
我得出的结论是,实际上“react hooks”并不是“render prop”模式的全面替代品。
Hooks 帮助您跨组件共享逻辑和状态。不确定您是否可以使用像“render props”那样的钩子将渲染逻辑从父级注入到子级。
此外,“React”文档中提到的“render props”仅作为某些旧版 API 的替代方案。