我在TypeScript中有以下代码,我试图在其中使用useRef
并分配arrayLength
const listRef = useRef(Array.from({ length: message.length }, a => React.createRef()));
但它从未被arrayLength填充,并以的形式出现
ListRef对象当前:[]
代码出了什么问题?为什么它从不获取数组值?
根据您告诉我们的,唯一的解释是,截至对useRef
的第一次调用,message.length
是0
。之后对useRef
的后续调用(例如,当组件被重新渲染时(将忽略传入的初始值,而不是返回第一次对useRef
的调用所创建的ref。
这里有一个简单的例子说明了这一点:
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>
如果目标是扩展/收缩引用数组以匹配message
,则必须明确执行此操作。我不会使用数组,我会使用Map
,由关于引用将用于的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>)}