据我了解,我可以将 refs 用于这样的单个元素:
const { useRef, useState, useEffect } = React; const App = () => { const elRef = useRef(); const [elWidth, setElWidth] = useState(); useEffect(() => { setElWidth(elRef.current.offsetWidth); }, []); return ( <div> <div ref={elRef} style={{ width: "100px" }}> Width is: {elWidth} </div> </div> ); }; ReactDOM.render( <App />, document.getElementById("root") ); <script src="https://unpkg.com/react@16/umd/react.production.min.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script> <div id="root"></div>
如何为元素数组实现这一点?显然不是那样的:(即使我没有尝试过,我也知道:)
const { useRef, useState, useEffect } = React; const App = () => { const elRef = useRef(); const [elWidth, setElWidth] = useState(); useEffect(() => { setElWidth(elRef.current.offsetWidth); }, []); return ( <div> {[1, 2, 3].map(el => ( <div ref={elRef} style={{ width: `${el * 100}px` }}> Width is: {elWidth} </div> ))} </div> ); }; ReactDOM.render( <App />, document.getElementById("root") ); <script src="https://unpkg.com/react@16/umd/react.production.min.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script> <div id="root"></div>
我已经看到了这个,因此也看到了这个。但是,我仍然对如何为这个简单案例实施该建议感到困惑。
ref 最初只是{ current: null }对象。useRef在组件渲染之间保持对这个对象的引用。currentvalue 主要用于组件引用,但可以保存任何内容。
{ current: null }
useRef
current
在某个时候应该有一个 refs 数组。如果数组长度在渲染之间可能会有所不同,则数组应相应地缩放:
const arrLength = arr.length; const [elRefs, setElRefs] = React.useState([]); React.useEffect(() => { // add or remove refs setElRefs((elRefs) => Array(arrLength) .fill() .map((_, i) => elRefs[i] || createRef()), ); }, [arrLength]); return ( <div> {arr.map((el, i) => ( <div ref={elRefs[i]} style={...}> ... </div> ))} </div> );
这段代码可以通过展开useEffect和替换来优化useState,useRef但应该注意的是,在渲染函数中做副作用通常被认为是一种不好的做法:
useEffect
useState
const arrLength = arr.length; const elRefs = React.useRef([]); if (elRefs.current.length !== arrLength) { // add or remove refs elRefs.current = Array(arrLength) .fill() .map((_, i) => elRefs.current[i] || createRef()); } return ( <div> {arr.map((el, i) => ( <div ref={elRefs.current[i]} style={...}> ... </div> ))} </div> );