将元素添加到列表后延迟并滚动到相同的滚动视图

Delay after prepending elements to a list and scroll to same scrolling view

当您滚动到列表中的某个位置并按“Space”时,新元素将添加到列表中。代码意图是保持与用户按下“Space”之前相同的滚动视图。项目被加载并持续几毫秒,滚动视图位于新的前置项目的顶部,然后滚动到保存的先前滚动视图。我想立即完成,没有让用户恼火的毫秒延迟。

有可能拿到吗?

代码:

import React, { useState, useEffect, useRef } from "react";
import "./styles.css";

export default function App() {
  const listRefs = useRef({});
  const scrollRef = useRef();
  const oldListHeight = useRef();

  const generateId = (length) => {
    let result = "";
    const characters =
      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    const charactersLength = characters.length;
    for (let i = 0; i < length; i++) {
      result += characters.charAt(Math.floor(Math.random() * charactersLength));
    }
    return result;
  };

  const generateList = () => {
    const html = [];

    for (let i = 0; i < Math.floor(Math.random() * 30) + 20; i++) {
      const id = generateId(15);

      listRefs.current[id] = React.createRef();
      html.push(
        <li ref={listRefs[id]} key={id}>
          {id}
        </li>
      );
    }

    return html;
  };

  const [htmlList, setHtmlList] = useState(generateList());

  useEffect(() => {
    setTimeout(() => {
      const listHeightDiff =
        scrollRef.current.scrollHeight - oldListHeight.current;
      scrollRef.current.scrollTo({
        top: scrollRef.current.scrollTop + listHeightDiff
      });
    }, 0);
  }, [htmlList]);

  useEffect(() => {
    window.addEventListener("keydown", handleKeyDown, false);

    return () => {
      window.removeEventListener("keydown", handleKeyDown, false);
    };
  }, []);

  const handleKeyDown = (e) => {
    if (e.key === " ") {
      oldListHeight.current = scrollRef.current.scrollHeight;
      setHtmlList((htmlList) => [generateList(), ...htmlList]);
    }
  };

  return (
    <div className="App">
      <div ref={scrollRef} className="wrapper">
        <ul>{htmlList}</ul>
      </div>
    </div>
  );
}

游乐场:

https://codesandbox.io/s/affectionate-antonelli-wkvvd?file=/src/App.js

我认为这是问题所在,

你的setHtmlList((htmlList) => [generateList(), ...htmlList]);

generateList() returns 一个数组,这样你的数组就变成了 [[some ids],oldids],

它变成了一个数组的数组,React 重新渲染了一切。你需要的是 [new ids,old ids].

要修复它,我必须将上面的行更改为

setHtmlList((htmlList) => [...generateList(), ...htmlList]);

注意 generateList() 上的扩展运算符。这将使数组变平,React 可以管理其余部分。

更新代码,

https://codesandbox.io/s/eloquent-cherry-6hxyo?file=/src/App.js:1572-1633