动态子布局的 Render Props 与 React Hooks

问题描述 投票:0回答:1

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
}
reactjs react-hooks react-props
1个回答
0
投票

我得出的结论是,实际上“react hooks”并不是“render prop”模式的全面替代品。

Hooks 帮助您跨组件共享逻辑和状态。不确定您是否可以使用像“render props”那样的钩子将渲染逻辑从父级注入到子级。

此外,“React”文档中提到的“render props”仅作为某些旧版 API 的替代方案。

© www.soinside.com 2019 - 2024. All rights reserved.