Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

react-portals-cache issue when using ref's #793

Open
ConnorTJolley opened this issue Dec 18, 2024 · 8 comments
Open

react-portals-cache issue when using ref's #793

ConnorTJolley opened this issue Dec 18, 2024 · 8 comments

Comments

@ConnorTJolley
Copy link

Describe the bug
It seems that if you have a registered component which uses a ref for it's rendering, when switching to a layout that also shares the same panel component, the rendering of that panel seems to completely break, seemingly the react-portals-cache is also empty for this element.

To Reproduce
Steps to reproduce the behavior:

I tried to replicate the behaviour without using the same package that I'm experiencing it with (Bryntum Grid due to licensing and account being required to download the package, but:

  • Register your components ensuring 1 is a functional component that uses a instantiates a ref backed class, i.e. BryntumGrid in our case
  • Ensure you have to layouts, both referencing the same panel
  • Load layout 1
  • Observe the panel is populated and working correctly
    image
  • Load layout 2
  • Observe the panel is now empty and the DOM shows an empty react-portals-cache element
    image
  • Close the panel
  • Re-add the panel
  • Observe the panel is now rendered correctly and working fine

This issue, I'm unsure whether it's based on the Bryntum library I'm using or whether it's something with how the dockview handles loading components that were loaded in previous layouts and any updating of refs that may be required when rendering in a new DOM location or whether it's just based on my implementation that is causing it, any insight would be greatly appreciated

As when you close and re-add the panel, it works perfectly fine again afterwards

Expected behavior
I'd expect that components shared across different layouts (Nested dock view, etc) would continue to render fine without having to close & re-add the panel

Screenshots
SC's attached as part of steps to reproduce

Desktop (please complete the following information):

  • Browser: Chrome
  • Version: 131.0.6778.140

Additional context
Add any other context about the problem here.

@mathuo
Copy link
Owner

mathuo commented Dec 20, 2024

react-portals-cache I assume is something that belongs to the third-party package's logic since it's not something found in dockview.

Happy to investigate but might need a little more info. When you say a component that "uses a ref for it's renderering" I'm not entirely sure what you mean by this in the context of React? Could you provide a small snippet of code to clarify please.

@ConnorTJolley
Copy link
Author

ConnorTJolley commented Dec 20, 2024

Sorry, yeah, so for example: https://bryntum.com/products/grid/examples/frameworks/react-vite/basic/dist/ we are using this grid component from Bryntum, we have a component which interacts with our context and uses the BryntumGrid to present the data, so we would have something like:

export const XGrid = (props: { gridRef: any }) => {
   // Other hook stuff and functions

   function buildGrid()
   {
       return (
          <BryntumGrid
            ref={props.gridRef}
            ...
          />
       );
   }

   return buildGrid();

}

Panel component declaration as:

const components = {
       grid: (props: IDockviewPanelProps) => {
             return <XGrid gridRef={gridRef} />
       }
}

With the gridRef being drilled down from the parent component which is using the ref along with another Bryntum component for it's drag and drop functionality (which I tested isn't the cause, as I've tried both defining the ref internally in the component and not interacting with the ref at all)

@ConnorTJolley
Copy link
Author

ConnorTJolley commented Dec 20, 2024

Also may be worth noting, I am using dockview following this example / setup https://codesandbox.io/p/sandbox/github/mathuo/dockview/tree/gh-pages/templates/dockview/nested/javascript

Each layout I'm referring is it's own Dockview instance, and switching the active 'panel' (dockview) loads it's own panels, essentially the root dock instance is structured like:

  • Root (Dockview instance)
    • Layout 1 (Dockview instance)
      • component_1 (Panel & component)
      • component_2 (Panel & component)
    • Layout 2 (Dockview instance)
      • component_2 (Panel & component)
      • component_5 (Panel & component)

So each nested dockview instance is sharing components that are all defined in the root dockview, the issue of the panel content being empty in my instance would be that component_2 would be declaring the BryntumGrid using the ref as detailed in the code snippet I posted previously, when switching the active panel which shows a different dockview instances panels, that is where the content is breaking, unless you close and re-open the panel

I also tried programmatically closing and re-opening the panel, to no success, it's still empty until you manually remove and re-add it

@mathuo
Copy link
Owner

mathuo commented Dec 20, 2024

How are you going about using the components props? Anything fancy here like custom parameters or is your application state parsed into the dockview components using a state management tool (i.e React Context, Redux etc etc)?

const MyGridComponent = (props: IDockviewPanelProps) => {
    return <div>{/** render something */}</div>;
};

const components = { 
    myGridComponent: MyGridComponent,
};

const Test = () => {
    const onReady = (event: DockviewReadyEvent) => {
        //
    };

    return <DockviewReact onReady={onReady} components={components} />;
};

@ConnorTJolley
Copy link
Author

ConnorTJolley commented Dec 20, 2024

How are you going about using the components props? Anything fancy here like custom parameters or is your application state parsed into the dockview components using a state management tool (i.e React Context, Redux etc etc)?

const MyGridComponent = (props: IDockviewPanelProps) => {
    return <div>{/** render something */}</div>;
};

const components = { 
    myGridComponent: MyGridComponent,
};

const Test = () => {
    const onReady = (event: DockviewReadyEvent) => {
        //
    };

    return <DockviewReact onReady={onReady} components={components} />;
};

I've made a codesandbox to emulate how we've set it all up and I have commented out code that would just fail without the package: https://codesandbox.io/p/sandbox/zealous-hopper-l6n2k8 hopefully that helps

With switching from Layout 1 to Layout 2 being when the grid panel would be empty unless you deleted it and re-added it manually

@mathuo
Copy link
Owner

mathuo commented Dec 22, 2024

Out of curiousity do you still experience the same issue if you set defaultRenderer='always' on each DockviewReact component?

@ConnorTJolley
Copy link
Author

From what I can remember, yeah, tried individually specifying the component to have always as the renderer and on the DockviewReact itself.

I have also tried unloading all panels in Layout 1's Dockview prior to loading any panels into Layout 2's Dockview, with no success either

Which, as another note which makes it even more confusing, we also have another panel that is using the BryntumGantt component: https://bryntum.com/products/gantt/examples/frameworks/react/javascript/gantt-schedulerpro/build/ which also uses a similar approach to providing a ref for it to use, but oddly this component works fine in both layouts (after unloading the panel in Layout1)

Which is also another reason why I was confused and was thinking it was either that the Dockview was doing something when trying to render the component and not passing through the ref properly or whether the library / component itself is doing something odd

@ConnorTJolley
Copy link
Author

I logged on this morning and verified that it does not change the outcome, I have also recorded the following video to demonstrate exactly what I mean, the main panels are the:

  • Layers & Shape (Bryntum Grid)
  • Gantt View (Bryntum Gantt)
2024-12-23.09-32-27.1.mp4

As you can see, switching between the nested dock views loads it's own layout of panels, both sharing the same components, the Layers & Shape panel just seems to lose it's content, but the Gantt View is perfectly fine, also shows that closing and re-adding the panel fixes it in the current layout (until you switch the active dockview)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants