From what you've told us, the only explanation is that message.length as of the first call to useRef is 0. Subsequent calls to useRef after that (e.g., when the component is re-rendered) will ignore the initial value you pass in, instead returning the ref created by the first call to useRef.
Here's a simple example showing that happening:
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>
If the goal is to expand/contract the array of refs to match message, you have to do that explicitly. I wouldn't use an array for it, I'd use a Map, keyed by some unique information about the entry in message that the ref will be used for. That way, the code isn't confused when things are inserted at the beginning of message, or in the middle, or when things are rearranged. That might look something like:
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());
}
}
...and then using them:
{message.map(entry => <whatever ref={messageRefs.get(entry.id)}>...</whatever>)}
const listRef = useMemo(() => messages.map(() => React.createRef<HTMLElement>()), [])- stackoverflow.com/questions/63451730/…TypeError: Cannot read property 'current' of undefinedexpecting 0 argument but got1`'