-
-
Notifications
You must be signed in to change notification settings - Fork 32.5k
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
[Tabs] Improve tab panels mounting behavior #21250
Comments
Hey! Really liking Material UI, but supporting the unmounting behavior described here would be very desirable. Any updates on this? :) |
@oliviertassinari I use simple solution to have always mounted TabPanels: export function TabPanel(props: any) {
const {
children,
className,
style,
value: id,
Container = DefaultContainer,
...other
} = props
const context = useTabContext()
if (context === null) {
throw new TypeError('No TabContext provided')
}
const tabId = context.value
return (
<div
className={className}
style={{
width: '100%',
...style,
position: 'absolute',
left: 0,
visibility: id === tabId ? 'visible' : 'hidden',
}}
{...other}
>
<Container>{children}</Container>
</div>
)
} |
No news on this? Aren't upvotes enough for being considered? |
@shayantabrizi Feel free to work on this problem. |
This solution load all tabs at begin, kind of
If we want to make
We can add a checker and change a bit like this export function TabPanel(props: any) {
const {
children,
className,
style,
value: id,
Container = DefaultContainer,
...other
} = props
const context = useTabContext()
if (context === null) {
throw new TypeError('No TabContext provided')
}
const tabId = context.value
const [visited, setVisited] = useState(false)
useEffect(() => {
if(id === tabId) {
setVisited(true)
}
}, [id, tabId]);
return (
<div
className={className}
style={{
width: '100%',
...style,
position: 'absolute',
left: 0,
visibility: id === tabId ? 'visible' : 'hidden',
}}
{...other}
>
{visted && <Container>{children}</Container>}
</div>
)
} |
If anybody wants to make a deep dive into React 18 then I would suggest investigating wrapping the panel content in I don't have a full picture for this yet hence why I suggest that somebody investigates this area since I believe tabs can really make use of React 18. Edit:
I think it's safe to assume that this will happen. |
@ambroseus |
@dnquang1996vn Did you mean to say instead of
|
@loetek Yeah i mean this. Thanks for checking me. I updated comment |
@oliviertassinari Just add to any tab panel content this line:
every time you switch a tab, mounting is done two times. |
Same here, I use official example, It always calls twice when I switch tabs. |
@ievgennaida @MukeZ |
@hoangtrung99 |
It's a strict mode of react is causing this. |
The example given here isn't very good for me as I couldn't use absolute positioning of the tabs in any way. Is there a more unobtrusive way? |
I'm new to MUI (currently using version 5.6) and I'd like to add my humble perspective on this issue, as a newcomer. The current behavior of the MUI Lab TabPanel, as far as I understand it, rather contradicts my a priori mental model of how a set of UI tabs should work: it took me a while just to realize that the reason my internal state was always reset was because the panel unmounts when going invisible, and mounts again when coming back into view (for a while I thought I did not understand something deeper with React hooks, until I had the idea to put a I understand that this makes sense performance-wise, and how I can work around it by putting my state elsewhere (using Redux or a parent component for instance), but still, for my use case, which is to have data grids with many controlling state variables inside each panel, I find that solution not terribly satisfying. So if there was an option to at least control that behavior, it would be ideal in my opinion. I will take the occasion to add that the reason why there are two sets of components, to implement tabs (one from MUI Core, the other from the Lab), is not very clear to me, when I read the documentation. The pros and cons of using each is also not fully clear, although I understand that by using the MUI Core set I will have greater control to implement the behavior I need, so that's what I will try next. |
How would an iframe in a tab be affected by the Offscreen API? Would that document still function and update as if it was simply in another tab? We are currently using the modified TabPanel code above because we have legacy UI being brought into tabs and the user needs to freely switch between them without losing their place. Not ideal, but unfortunately for those of us working with legacy, an iframe can be a desired way of encapsulating old functionality. And I believe some services still utilize iframes or DOM injection via JS which could require similar behavior. |
Just commenting to voice my support for implementing better behavior for tabs, or at least making the docs more clearly address their behavior. I had no idea they unmounted components like this until after I'd sunk a fair bit of time into a layout based around them. It's obviously unexpected behavior for a layout component to have, and not trivial to work around, so it should either be fixed, or the behavior should be called out loudly in the docs. |
This is not a solution for a majority of cases. If your tab content is of variable height (very likely), you'll get stuck again on account on absolute positioning. Once you go absolute, your content will no longer have a natural height. You'll be forced to resort to annoying JS hacks to get the height working again. The best "workaround" at the moment is to keep your state one level up more than you need it. Build stateless tab content components and keep the state in the component/function that's rendering the TabContext. When MUI has a native solution, refactor this component/function. Yes, this is not ideal, I understand that, but it's the best we can make of what we have at the moment. |
Would there be an fix for this available for the Tabs Component? I have an example of code here to recreate the issue: https://codesandbox.io/s/amazing-margulis-brfny5 |
you can use redux to restore the value |
Thanks for sharing good way. when i use that code, I found a potential but fatal bug. When I use same code that you posted, there is a problem that didn't remove also, so I suggest
|
There are some cases where other MUI components are constructed in a way that prevents the external state workaround. For example, with controlled row selection in DataGrid, the re-render itself triggers
|
Based on #21241, we might have an opportunity to improve the
TabPanel
mounting behavior. We can potentially fix these problems:I have used the following benchmark list https://trello.com/c/JM6Zh3YW/2642-tabs to look at what the others are doing
forceRender
prop to render all the panels)renderAll
prop to render all the panels)In the future, React mentions maybe solving this in the framework: oliviertassinari/react-swipeable-views#453 (comment), by providing better support for offscreen rendering.
What do you guys think about these different tradeoffs? It seems that we need, at least, a way to enable the mounting of all the panels.
The text was updated successfully, but these errors were encountered: