I am accessing availableWidgets as a widget?.component
in GridItem to iterate component but now I want to pass GridItem Ref to widget components.
Give me Suggestion you any.
const availableWidgets = [
{},
{
component: <DashboardsGuide />,
id: "1"
},
{
component: <DashboardsWeather />,
id: "2"
},
{
component: <DashboardsTraining />,
id: "3"
},
];
Here, the available widgets content the component and I want to pass parent ref.current
into this widget but I am not getting idea how to pass ref to its child component while iterating it.
If it is possible then give fruitful suggestion
I had tried forwardRef
to make it possible but not get succeed.
const GridItem = React.forwardRef(function GridItem(
{ className, style, children, item, widget, id, ...rest },
ref
) {
return (
<div
id={`width-height-${id}`}
className={`grid-item ${className}`}
style={style}
ref={ref}
{...rest}
>
{console.log(ref?.current?.offsetHeight, ref?.current?.offsetWidth)}
{widget?.component}
{children}
</div>
);
});
I am using React Grid Layout library.
function GridLayout({ layouts, toggle }) {
return (
<ResponsiveGridLayout
// className="layout"
layouts={layouts}
rowHeight={20}
isDraggable={toggle ? true : false}
isResizable={toggle ? true : false}
margin={[20, 20]}
onLayoutChange={(...e) => {
localStorage.setItem("layouts", JSON.stringify(e[1]));
}}
breakpoints={{ lg: 1280, md: 992, sm: 767, xs: 480, xxs: 0 }}
cols={{ lg: 24, md: 20, sm: 12, xs: 8, xxs: 4 }}
>
{layouts.lg.map((item) => (
<GridItem id={item.i} key={item.i} widget={availableWidgets[item.i]} />
))}
</ResponsiveGridLayout>
);
}
By using
{layouts.lg.map((item) => (
<GridItem id={item.i} key={item.i} widget={availableWidgets[item.i]} />
))}
I am iterating widgets
If I'm understanding correctly, GridItem
needs to create a React ref and attach it to the div
it's rendering, and pass the ref along to the child widget component to access the current value of (i.e. the offset).
For this I suggest a small change to the availableWidgets
array so as to allow you to instantiate the components as JSX when rendering and inject any props then.
const availableWidgets = [
{},
{
component: DashboardsGuide,
id: "1"
},
{
component: DashboardsWeather,
id: "2"
},
{
component: DashboardsTraining,
id: "3"
},
];
Next have GridItem
create the React ref, attach it to the div
and instantiate the widget component to pass the ref in a prop.
const GridItem = ({
className,
style,
children,
item,
widget = {},
id,
...rest
}) => {
// (1) Create a React ref
const gridItemRef = React.useRef();
// (3) get widget component and rename to valid PascalCase name
const { component: Widget } = widget;
// Log the ref values in an intentional side-effect
React.useEffect(() => {
const { offsetHeight, offsetWidth } = gridItemRef.current;
console.log(offsetHeight, offsetWidth);
});
return (
<div
id={`width-height-${id}`}
className={`grid-item ${className}`}
style={style}
ref={gridItemRef} // (2) attach ref
{...rest}
>
{Widget && <Widget gridItemRef={gridItemRef} />} // (4) render Widget and pass ref prop
{children}
</div>
);
};
Inside each widget component (DashboardsGuide
, DashboardsWeather
, and DashboardsTraining
) access the passed GridItem
's gridItemRef
via props.