useRef
只是部分类似于React的ref
(仅具有current
字段的对象结构)。
useRef
钩子旨在在渲染之间存储一些数据,并且更改该数据不会触发重新渲染(与useState
不同)。
还要温馨提示:最好避免在循环或if
中初始化钩子。这是hooks的第一条规则。
有了这个想法,我们:
create array and keep it between renders by useRef
we initialize each array's element by createRef()
we can refer to list by using .current
notation
const Component = () => {
let refs = useRef([React.createRef(), React.createRef()]);
useEffect(() => {
refs.current[0].current.focus()
}, []);
return (<ul>
{['left', 'right'].map((el, i) =>
<li key={i}><input ref={refs.current[i]} value={el} /></li>
)}
</ul>)
}
这样我们就可以安全地修改数组(比如通过改变长度)。但是不要忘记,修改被存储在
useRef
中的数据不会触发重新渲染。因此,为了使改变长度重新渲染,我们需要使用
useState
。
const Component = () => {
const [length, setLength] = useState(2);
const refs = useRef([React.createRef(), React.createRef()]);
function updateLength({ target: { value }}) {
setLength(value);
refs.current = refs.current.splice(0, value);
for(let i = 0; i< value; i++) {
refs.current[i] = refs.current[i] || React.createRef();
}
refs.current = refs.current.map((item) => item || React.createRef());
}
useEffect(() => {
refs.current[refs.current.length - 1].current.focus()
}, [length]);
return (<>
<ul>
{refs.current.map((el, i) =>
<li key={i}><input ref={refs.current[i]} value={i} /></li>
)}
</ul>
<input value={refs.current.length} type="number" onChange={updateLength} />
</>)
}
同时,不要在首次渲染时尝试访问refs.current[0].current
- 这将引发错误。
请注意:
return (<ul>
{['left', 'right'].map((el, i) =>
<li key={i}>
<input ref={refs.current[i]} value={el} />
{refs.current[i].current.value}</li> // cannot read property `value` of undefined
)}
</ul>)
所以你要么将其作为{{保护}}
return (<ul>
{['left', 'right'].map((el, i) =>
<li key={i}>
<input ref={refs.current[i]} value={el} />
{refs.current[i].current && refs.current[i].current.value}</li> // cannot read property `value` of undefined
)}
</ul>)
或在useEffect
钩子中访问它。原因:ref
在元素呈现后绑定,因此在第一次运行渲染时尚未初始化。
useRef(elts.map(React.createRef))
恰好是我一直在寻找的,可以使函数组件不会丢掉我的引用。 - ohsullyconst refs = useRef( new Array(2).fill(React.createRef()));
。这会引起问题吗? - Shofolconst refs = useRef([...new Array(3)].map(() => React.createRef()));
是一个更好的选择。 - SNYDERHAUS