我在 TypeScript 中有以下代码,我试图在其中使用useRef
和分配 arrayLength
const listRef = useRef(Array.from({ length: message.length }, a => React.createRef()));
但它永远不会填充 arrayLength 并作为
ListRef 对象当前:[]
代码有什么问题?为什么它从不采用数组值?
我在 TypeScript 中有以下代码,我试图在其中使用useRef
和分配 arrayLength
const listRef = useRef(Array.from({ length: message.length }, a => React.createRef()));
但它永远不会填充 arrayLength 并作为
ListRef 对象当前:[]
代码有什么问题?为什么它从不采用数组值?
从您告诉我们的情况来看,唯一的解释是message.length
在第一次调用时useRef
是0
. 之后的后续调用useRef
(例如,重新渲染组件时)将忽略您传入的初始值,而是返回第一次调用创建的 ref useRef
。
这是一个简单的示例,显示了这种情况:
const { useRef, useState, useEffect } = React;
function Example({message}) {
console.log(`Component rendered, message.length = ${message.length}`);
const listRef = useRef(Array.from({ length: message.length }, a => React.createRef()));
console.log(`Component rendered, listRef.current.length = ${listRef.current && listRef.current.length}`);
return <div>x</div>;
}
function Parent() {
const [message, setMessage] = useState<([]);
useEffect(() => {
setTimeout(() => {
setMessage([1, 2, 3]);
}, 800);
}, []);
return <Example message={message} />;
}
ReactDOM.render(<Parent/>, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js"></script>
如果目标是扩展/收缩 refs 数组以匹配message
,则必须明确执行此操作。我不会为它使用数组,我会使用, 由有关将使用 refMap
的条目的一些唯一信息键入。message
这样,当在 的开头message
或中间插入内容或重新排列内容时,代码不会混淆。这可能看起来像:
const {current: messageRefs} = useRef<Map<someType, React.RefObject<HTMLElement>>(new Map());
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// \
// −− this part is TypeScript-
// specific; update the
// `someType` part to match
// the type of the unique
// information you're using,
// and the `HTMLElement` part
// to match the type of
// element you're storing in
// the ref
for (const {id} of message) {
if (!messageRefs.get(id)) {
messageRefs.set(id, React.createRef());
}
}
...然后使用它们:
{message.map(entry => <whatever ref={messageRefs.get(entry.id)}>...</whatever>)}