React Parent 组件计算 Child 组件的宽度和高度
React Parent component calculating width and height of Child Component
我有一个 Parent 组件在屏幕上重复通用 Child SVG 组件。
为了做到这一点,Parent 组件需要知道 child 的尺寸。
我曾经像这样将它们存储在 child 组件中(我知道这很不寻常但它有效)
function Child() {
return <path id="child" />
}
Child.width = 100
Child.height = 80
然后我曾经像这样在 parent 组件上阅读它们
function Parent(props) {
let width = props.children.type.width
let height = props.children.type.height
return Array.from(Array(props.times), (e, i) => {
return <Transform key={i} x={width*i} y={height*i}>
{props.children}
</Transform>
})
}
我想要的是 Parent 容器自行计算 child 的尺寸,因此它们不是静态的。
我知道我需要使用这样的引用访问 child 的 dom
function Parent(props) {
const test = React.useCallback(node => {
if (node !== null) {
const box = node.getBBox()
console.log(box) //this works
var width = box.width //this works too late
var height = box.height
}
}, []);
return Array.from(Array(props.times), (e, i) => {
return <Transform key={i} x={width*i} y={height*i}>
<g ref={test}> {props.children}</g>
</Transform>
})
}
但正如我想象的那样,React 不会等待我的回调来执行其余代码,所以它说宽度和高度未定义。
如何获得第一个元素的宽度和高度,然后让 Parent 组件完成他的工作?也许有悬念?
非常感谢任何帮助!
首先你可以通过url使用svg作为背景图片并放置背景重复和调整大小。但如果你想要这种方法,我们就去吧。
forwardRef/refs 有很多方法可以达到这种效果。下面的代码是第一个想到的
我建议您将 svg 作为 jsx/tsx file/react 组件 - 这样,否则您需要将 parentRef 提供给 layoutEffect dependancies
import React, { useLayoutEffect, useRef } from 'react';
import logo from './logo.svg';
import './App.css';
import Logo from './Logo';
const Parent1: React.FC = ({ children }) => {
const parentRef = useRef<HTMLDivElement | null>(null);
useLayoutEffect(() => {
parentRef.current?.childNodes.forEach((node: any) =>
console.log({ height: node?.clientHeight, width: node?.clientWidth }),
);
}, []);
return (
<div className='parent1' ref={parentRef}>
{children}
</div>
);
};
function App() {
return (
<div className='App'>
<Parent1>
{Array(Math.ceil(Math.random() * 25 + 10))
/**
If you will decide to go img way - you need to place
parentRef as a dependancy for the layoutEffect
.fill(() => <img src={logo} alt='' />)
*/
.fill(Logo)
.map((E, i) => {
return <E key={i} />;
})}
</Parent1>
</div>
);
}
所以解决方案是更新 useEffect 中组件的状态,以便我们的视图在数据可用时得到更新:
function Parent(props) {
const [height, setHeight] = React.useState()
const [width, setWidth] = React.useState()
const test = React.useCallback(node => {
if (node !== null) {
const box = node.getBBox()
setWidth(box.width)
setHeight(box.height)
}
}, []);
return Array.from(Array(props.times), (e, i) => {
return <Transform key={i} x={width*i} y={height*i}>
<g ref={test}> {props.children}</g>
</Transform>
})
}
我有一个 Parent 组件在屏幕上重复通用 Child SVG 组件。
为了做到这一点,Parent 组件需要知道 child 的尺寸。
我曾经像这样将它们存储在 child 组件中(我知道这很不寻常但它有效)
function Child() {
return <path id="child" />
}
Child.width = 100
Child.height = 80
然后我曾经像这样在 parent 组件上阅读它们
function Parent(props) {
let width = props.children.type.width
let height = props.children.type.height
return Array.from(Array(props.times), (e, i) => {
return <Transform key={i} x={width*i} y={height*i}>
{props.children}
</Transform>
})
}
我想要的是 Parent 容器自行计算 child 的尺寸,因此它们不是静态的。
我知道我需要使用这样的引用访问 child 的 dom
function Parent(props) {
const test = React.useCallback(node => {
if (node !== null) {
const box = node.getBBox()
console.log(box) //this works
var width = box.width //this works too late
var height = box.height
}
}, []);
return Array.from(Array(props.times), (e, i) => {
return <Transform key={i} x={width*i} y={height*i}>
<g ref={test}> {props.children}</g>
</Transform>
})
}
但正如我想象的那样,React 不会等待我的回调来执行其余代码,所以它说宽度和高度未定义。
如何获得第一个元素的宽度和高度,然后让 Parent 组件完成他的工作?也许有悬念? 非常感谢任何帮助!
首先你可以通过url使用svg作为背景图片并放置背景重复和调整大小。但如果你想要这种方法,我们就去吧。 forwardRef/refs 有很多方法可以达到这种效果。下面的代码是第一个想到的 我建议您将 svg 作为 jsx/tsx file/react 组件 - 这样,否则您需要将 parentRef 提供给 layoutEffect dependancies
import React, { useLayoutEffect, useRef } from 'react';
import logo from './logo.svg';
import './App.css';
import Logo from './Logo';
const Parent1: React.FC = ({ children }) => {
const parentRef = useRef<HTMLDivElement | null>(null);
useLayoutEffect(() => {
parentRef.current?.childNodes.forEach((node: any) =>
console.log({ height: node?.clientHeight, width: node?.clientWidth }),
);
}, []);
return (
<div className='parent1' ref={parentRef}>
{children}
</div>
);
};
function App() {
return (
<div className='App'>
<Parent1>
{Array(Math.ceil(Math.random() * 25 + 10))
/**
If you will decide to go img way - you need to place
parentRef as a dependancy for the layoutEffect
.fill(() => <img src={logo} alt='' />)
*/
.fill(Logo)
.map((E, i) => {
return <E key={i} />;
})}
</Parent1>
</div>
);
}
所以解决方案是更新 useEffect 中组件的状态,以便我们的视图在数据可用时得到更新:
function Parent(props) {
const [height, setHeight] = React.useState()
const [width, setWidth] = React.useState()
const test = React.useCallback(node => {
if (node !== null) {
const box = node.getBBox()
setWidth(box.width)
setHeight(box.height)
}
}, []);
return Array.from(Array(props.times), (e, i) => {
return <Transform key={i} x={width*i} y={height*i}>
<g ref={test}> {props.children}</g>
</Transform>
})
}