我想每次绘制 React Native View 的大小并将其保存为状态。如果元素布局未更改,则效果不应运行。
使用基于类的组件很容易,其中可以使用onLayout。但是,在使用React Hooks的功能组件中该怎么办?
我已经读过useLayoutEffect。如果那是要走的路,您有使用它的示例吗?
我制作了一个名为useDimensions的自定义钩子。这是我所走的距离:
const useDimensions = () => {
const ref = useRef(null);
const [dimensions, setDimensions] = useState({});
useLayoutEffect(
() => {
setDimensions(/* Get size of element here? How? */);
},
[ref.current],
);
return [ref, dimensions];
};
然后我使用钩子并将引用添加到要测量尺寸的视图中。
const [ref, dimensions] = useDimensions();
return (
<View ref={ref}>
...
</View>
);
我尝试调试ref.current
,但是没有发现有用的东西。我还尝试了效果钩子内的measure():
ref.current.measure((size) => {
setDimensions(size); // size is always 0
});
答案 0 :(得分:11)
如果您想要一个更独立的版本,这里是React Native的自定义钩子版本:
const useComponentSize = () => {
const [size, setSize] = useState(null);
const onLayout = useCallback(event => {
const { width, height } = event.nativeEvent.layout;
setSize({ width, height });
}, []);
return [size, onLayout];
};
const Component = () => {
const [size, onLayout] = useComponentSize();
return <View onLayout={onLayout} />;
};
答案 1 :(得分:3)
作为对 matto1990's answer,并回答Kerkness的问题-这是一个示例自定义钩子,提供了x,y位置以及布局大小:
const useComponentLayout = () => {
const [layout, setLayout] = React.useState(null);
const onLayout = React.useCallback(event => {
const layout = event.nativeEvent.layout;
setLayout(layout);
}, [])
return [layout, onLayout]
}
const Component = () => {
const [{ height, width, x, y }, onLayout] = useComponentSize();
return <View onLayout={onLayout} />;
};
答案 2 :(得分:2)
您有一个正确的想法,它只需要进行一些调整...主要是,将元素ref提交并在elementRef.current
依赖项数组中使用elementRef(不是useEffect
)。
(关于useEffect
与useLayoutEffect
,因为您只是测量而不是对DOM进行变异,所以我相信useEffect
is the way to go,但是您可以像这样交换掉它-如果需要的话,
const useDimensions = elementRef => {
const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
useEffect(() => {
const el = elementRef.current;
setDimensions({ width: el.clientWidth, height: el.clientHeight });
}, [elementRef]);
return [dimensions];
};
像这样使用它:
function App() {
const divRef = useRef(null);
const [dimensions] = useDimensions(divRef);
return (
<div ref={divRef} className="App">
<div>
width: {dimensions.width}, height: {dimensions.height}
</div>
</div>
);
}
已编辑以添加React Native版本:
对于React Native,您可以将useState
与onLayout
一起使用,如下所示:
const App=()=>{
const [dimensions, setDimensions] = useState({width:0, height:0})
return (
<View onLayout={(event) => {
const {x, y, width, height} = event.nativeEvent.layout;
setDimensions({width:width, height:height});
}}>
<Text}>
height: {dimensions.height} width: {dimensions.width}
</Text>
</View>
);
}