所以我有一个数据数组,并且我正在使用该数据生成一个组件列表。我想在每个生成的元素上有一个引用来计算高度。 我知道如何使用 Class 组件来做到这一点,但我想使用 React Hooks 来做到这一点。
这是一个解释我想要做什么的例子:
import React, {useState, useCallback} from 'react'
const data = [
{
text: 'test1'
},
{
text: 'test2'
}
]
const Component = () => {
const [height, setHeight] = useState(0);
const measuredRef = useCallback(node => {
if (node !== null) {
setHeight(node.getBoundingClientRect().height);
}
}, []);
return (
<div>
{
data.map((item, index) =>
<div ref={measuredRef} key={index}>
{item.text}
</div>
)
}
</div>
)
}
不确定我完全理解你的意图,但我认为你想要这样的东西:
const {
useState,
useRef,
createRef,
useEffect
} = React;
const data = [
{
text: "test1"
},
{
text: "test2"
}
];
const Component = () => {
const [heights, setHeights] = useState([]);
const elementsRef = useRef(data.map(() => createRef()));
useEffect(() => {
const nextHeights = elementsRef.current.map(
ref => ref.current.getBoundingClientRect().height
);
setHeights(nextHeights);
}, []);
return (
<div>
{data.map((item, index) => (
<div ref={elementsRef.current[index]} key={index} className={`item item-${index}`}>
{`${item.text} - height(${heights[index]})`}
</div>
))}
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<Component />, rootElement);
.item {
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #ccc;
}
.item-0 {
height: 25px;
}
.item-1 {
height: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
<div id="root"/>
不需要有副作用的
useEffect
或其他脆弱的方法。根据官方指导,你可以使用“refcallbacks”。
当需要设置 ref 时,React 将使用 DOM 节点调用您的 ref 回调,而当需要清除它时,将使用 null
来调用您的 ref 回调。这使您可以维护自己的数组或
Map
,并通过索引或某种 ID 访问任何引用。例如:
import { useRef } from "react";
const data = [{
id: 1,
text: 'test1'
},{
id: 2,
text: 'test2'
}
]
const Component = () => {
const itemsRef = useRef(new Map());
return (
<div>
{data.map((item) => (
<div
key={item.id}
ref={el => el ? itemsRef.current.set(v.id, el) : itemsRef.current.delete(v.id)}>
{item.text}
</div>
))}
</div>
);
};
如果您的数组没有自然 ID,您始终可以回退到良好的 ol' 索引,但需要注意与在其他地方使用它作为键类似的警告。
const Item = ({ text }) => {
const ref = useRef()
const [ height, setHeight ] = useState()
useLayoutEffect(() => {
setHeight( ref.current.getBoundingClientRect().height )
}, [])
return <div ref={ref}>{text}</div>
}