Closed alinzk closed 4 years ago
this is a known limitation of PanelStack
. definitely open to reviewing a fix PR @anawaz42. your possible solution seems workable.
This is indeed a known limitation. Your idea, however, will not fix it. The initialPanel
is put on the React state of the PanelStack
only once, any changes to the prop are ignored after that. The fact that the PanelView
doesn't re-render is not relevant here.
There is currently no way to ever change the props of an open panel. We internally use redux-connected panels to make them react to changes in the app.
The only possible solution I see is to allow making the PanelStack
a controlled component, so you can maintain the entire stack of panels as you wish, including changes to existing panels' props.
Thanks for responding to this. The explanation does make sense and using connected panels is definitely a good option.
Apart from making component controlled, I think I have some other ideas, I'll work a bit and share them.
I found a very good solution!
Use a React <Context>
instead.
Context provides a way to pass data through the component tree without having to pass props down manually at every level.
https://reactjs.org/docs/context.html
This is my wrapper component:
const Context = React.createContext({} as MenubarProps);
function Menubar(props: MenubarProps) {
const [panels, setPanels] = useState<IPanel<{}>[]>([
{
component: Settings,
props: {},
title: "Settings",
},
]);
return (
<Context.Provider value={props}>
<PanelStack
className="Menubar"
initialPanel={panels[0]}
onOpen={(new_) => setPanels([new_, ...panels])}
onClose={() => setPanels(panels.slice(1))}
/>
</Context.Provider>
);
}
A helper to automatically wrap the panel components:
const withContext = (Component: (props: PanelProps) => any) => (panelProps: any) => (
<Context.Consumer>{(props) => <Component {...props} {...panelProps} />}</Context.Consumer>
);
Example of one of the panels:
const SelectNetwork = withContext(({
closePanel, // <--- from PanelStack's props
setNetwork, ap, setAp, // <--- my custom props
}: PanelProps) => {
return (
<CaptivePortal
onConnected={(essid) => {
closePanel();
setNetwork(essid);
}}
onAP={() => {
closePanel();
setNetwork("");
}}
ap={ap}
setAp={setAp}
vertical
/>
);
});
Type:
type PanelProps = IPanelProps & MenubarProps; // PanelStack's props + my custom props
Closing this old issue as it appears it can be worked around with controlled mode (#3601) and there are other approaches to data management (redux, react context, etc.) which allow you to connect indirectly to component trees.
Environment
Steps to reproduce
Actual behavior
The count on top is updated but not inside the
PanelStack
Expected behavior
The count should be updated at both places.
Possible solution
Not sure, but I think passing in the props directly to
PanelView
here will cause it to re-render