将元素添加到列表后延迟并滚动到相同的滚动视图
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
当您滚动到列表中的某个位置并按“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