根据父尺寸渲染React子组件

时间:2019-08-21 12:15:32

标签: reactjs

我需要从UV坐标渲染React子组件(规范化坐标/ U和V通常在[0; 1]范围内)

但是我不知道在渲染儿童时如何获得父尺寸。

我想执行类似的操作(使用tsx):

const Child = (props: {u:Number, v:Number}) => 
      <circle cx={parentClientWidth*props.u} cy={parentClientHeight*props.v} r="5" fill="black"></circle>;

const Parent = () => 
      <svg>
         <Child u={0.3} v={0.5} />
      </svg>;

我愿意使用上下文对象吗?...


const Child = (props: {u:Number, v:Number}) => {
      const workspace= useContext(WorkspaceContext);

      return <circle cx={workspace.width*u} cy={workspace.height*v} r="5"></circle>;
}

注意: 在这种简单的情况下,我可以将百分数用于cx和cy坐标,但实际情况要复杂得多...

1 个答案:

答案 0 :(得分:0)

在研究了很多反应文档之后,我终于找到了一种对我来说似乎不太hacky的方法……但是我仍在学习,因此可能还有另一种更好的方法(关于性能?可读性?……) 无论如何,这是我当前解决方案的想法:

// Shares the dimensions of the workspace through children
const WorkspaceContext = createContext();

/** A child component.
 * It should be placed at specified (u,v) within the parent component. 
 */
const Child = (props: {u:Number, v:Number}) => {
     const workspaceContext = useContext(WorkspaceContext);
     return <circle cx={workspaceContext.width*props.u} cy={workspaceContext.height*props.v} r="5" fill="black"></circle>;
};

/** The parent SVG component */
const Parent = () => {
      const [dimensions, setDimensions] = useState({
            width: undefined, 
            height:undefined, 
            outdated: true // Triggers a re render when changed
       });

      // I'm using the ref callback to get the svg dimensions
      const parentRefCallback = (element: SVGSVGElement) => {
        if(element) {
            const width = element.clientWidth;
            const height = element.clientHeight;
            if(dimensions.width !== width || dimensions.height !== height) {
                setDimensions({width, height, outdated: false});
            }
        }
    };

    useEffect(() => {
        const handler = () => setDimensions({...dimensions, outdated: true}); // re renders!
        window.addEventListener('resize', handler);
        return () => window.removeEventListener('resize', handler);
    }, [])

      return <svg ref={parentRefCallback}>
         <WorkspaceContext.Provider value={dimensions}>
             <Child u={0.3} v={0.5} />
         </WorkspaceContext.Provider>
      </svg>;
}