【问题标题】:How can I render component one by one?如何一个一个渲染组件?
【发布时间】:2020-09-10 18:53:09
【问题描述】:

我想限制父容器组件可以容纳的组件数量。

假设我有一个项目容器,我在其中渲染了数十个 Item 组件。容器的高度限制为220px,每个Item 的高度为50px(为简单起见,实际代码中的Item 高度不同)。

使用 React,我想限制容器可以容纳的 Item 组件的数量,相对于它的高度。因此,在将每个Item 放入容器之前,我需要验证容器是否没有溢出,如果是,则停止向其中渲染更多项目。

我使用以下代码来实现:

  const [canRender, setCanRender] = useState(true);

  useEffect(() => {
    const parent = ref.current.parentElement;
    setCanRender(parent.clientHeight <= parent.scrollHeight);
  }, []);

在给定的示例中,应该只渲染 3 个 Item 组件,因为容器无法容纳更多。 我的问题是 React 会立即渲染所有组件(由于未同步设置状态?)。

Click to see mock example

如何有条件地渲染Item组件并检查容器溢出?

【问题讨论】:

  • 我想你可以一个一个地设置Items数组,并有一个每次检查滚动高度的挂载钩子?它很可能会破坏你正在做的任何事情的目的。我建议你对太多的项目使用最佳的猜测时间,然后根据它进行调整,或者使用无限滚动插件或其他东西。当然,我不知道你到底想用这个实现什么,所以可能你必须这样做。
  • @user120242 使用钩子不会有什么不同,因为我将处理相同的状态问题并且一次性渲染项目。插件对我来说不是一个选项,因为我只想在某些情况下有条件地显示或隐藏项目。所以与无限滚动无关。
  • 问题的核心部分是您想要一个生命周期,以便您可以根据父参考进行优化。由于它是无状态的,因此您将无法使用函数式语法来获得它。您将需要使用类语法并使用shouldComponentUpdate 来检查父级的状态。 stackoverflow.com/questions/40909902/…
  • 我不建议这样做,但是根据您的要求,您可以为每个 Item 一个一个渲染的 Items 设置数据数组,以强制按顺序重新渲染每个 Item。您显然会挂钩 setState ,以便它无法捆绑 setState 更新和挂钩安装。您将向每个渲染的项目传递一个回调函数(可能作为道具)以挂钩它们的安装以进行您的滚动高度检查。 Jango 的建议听起来更好,但我不知道您将如何处理明确要求每个项目的 DOM 回流计算,这肯定会是一个 PITA。
  • @user120242 是的,我觉得这种相对简单的任务缺少功能。

标签: javascript css reactjs react-hooks


【解决方案1】:

只需将项目渲染逻辑移至 app.js。

working demo is here

App.js(编辑:优化代码)

export default function App() {
  const [count, setCount] = useState([]);
  const ref = useRef(null);
  useEffect(() => {
    if (ref.current.clientHeight >= ref.current.scrollHeight) {
      setCount(item => [...item, <Item key={Math.random()} />]);
    }
  }, [count]);

  return (
    <div ref={ref} className="container">
      {count}
    </div>
  );
}

Item.js

const Item = () => {
  return <div className="bar">Bar</div>;
};

export default Item;

附言考虑not to use math.random for keys

【讨论】:

  • 这是一个很好的解决方案,但是如果我事先不知道item 数组怎么办?比如说,我将创建一个钩子,让某些组件使用这种行为。我如何找出要迭代的项目?我可以考虑在主组件中使用一个状态,然后在初始渲染时注册每个组件?
  • @RA 没关系吗?如果您稍后添加了新项目,则无论如何您都必须更新道具/状态。只需将其从道具中拉出即可。协调应处理优化并防止内容闪现。显然 gdh 的实现是硬编码的(他误解了你的目标,因为他提到 key=Math.random 并且他的原始代码不起作用,哈哈)并且必须调整代码以使用(和挂钩)你的道具来生成,但想法保持不变(好吧,您将重写代码,但一项一项的想法是相同的)。
  • @user120242 Array 仅用于演示目的。假设您有一个组件A 和组件B,它们是containerchildren 在某些时候 - 由于挂钩,您可以强制这些组件的某些行为。所以想法是在组件A和组件B中使用useCheckOverflow钩子,现在由我们创建的钩子来验证这些组件是否可以放入container(通常是容器=elementRef.current.parentElement )。如果元素不会导致溢出 - 显示它,否则隐藏(返回 null)。所以我们不能在这里使用数组。
  • 听起来像是与 Jango 的洞察力有关的问题。该解决方案将始终存在问题,因为父级或更高级别本质上是需要决定允许渲染的人,并且应该转换数据以匹配该解决方案,因为您本质上是在转换用于渲染子级的数据。 (组件通常应该设置为具有可预测结构的 UI)您必须重构并在您提到时将回调传递给父控制器以逐一执行。你仍然需要一些东西(硬编码?)“类似数组”来检查溢出
  • @RA 我认为这个问题将受益于您创建一个具体的演示来显示(必需的)架构,该架构需要根据溢出以您希望的方式呈现。否则,它可能只是一个无处可去的讨论,因为很难想象你的问题的 PoC 以及要提供的 PoC 解决方案。
猜你喜欢
  • 2013-01-20
  • 2021-12-04
  • 1970-01-01
  • 1970-01-01
  • 2020-09-04
  • 2021-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多