Comments (7)
@joepvl So you mean react-tabs cache by default if all props are same on next visit ?
Which part of my comment led you to that conclusion? I'm going to assume by "next visit" you mean the next time a TabPanel
is selected.
Just to be clear, memo
has no explicit interaction with this library. All react-tabs
does is:
- by default: render (as in mount!) only the content of the
TabPanel
that corresponds to the selected index - if you pass
forceRenderTabPanel
toTabs
: always render the content of allTabPanel
s. This means that they will only be mounted once β of course you should still wrap them inmemo
if you don't want them to be rerendered whenTabs
is rerendered. - if you pass
forceRender
to a subset of yourTabPanel
s: always render the content of all TabPanels that have theforceRender
prop, in addition to that of the currently activeTabPanel
if that does not have theforceRender
prop
I think there may be a fundamental misunderstanding here β there is a difference between components rendering and components rerendering. The word "render" in forceRenderTabPanel
refers to mounting the component, so that the VDOM tree will look like this (simplified for illustration purposes):
Example 1, without `forceRenderTabPanel`:
Tabs
TabList
Tab 0
Tab 1 (active)
Tab 2
TabPanel 0
TabPanel 1 (corresponds to active tab)
Children of TabPanel 1
TabPanel 2
vs.
Example 2, with `forceRenderTabPanel`:
Tabs
TabList
Tab 0
Tab 1 (active)
Tab 2
TabPanel 0 (inactive, but still rendered ("mounted") because of `forceRenderTabPanel`)
Children of TabPanel 0
TabPanel 1 (corresponds to active tab)
Children of TabPanel 1
TabPanel 2 (inactive, but still rendered ("mounted") because of `forceRenderTabPanel`)
Children of TabPanel 2
In example 1, when you switch to Tab 0
, the contents of TabPanel 1
will be unmounted and that of TabPanel 0
will be mounted. When you switch back to Tab 1
, the reverse will happen, and no amount of memoizing the React component in TabPanel 1
will prevent it from being rendered (i.e. the function being executed) again. That is just how React works!
In example 2, the content of all TabPanel
s will be mounted as soon as the Tabs
component is mounted. Great, now you will not refetch when switching tabs! However, since all your TabPanel
content now renders (is mounted) immediately, all those components will do their expensive operations (e.g. fetching data). There's a good chance you don't want that either. react-tabs
does not include functionality out-of-the-box to deal with this problem.
One way to deal with this is to only mount TabPanel
content once, when the tab is first activated. This can be achieved by adding the forceRender
prop to a TabPanel
only after it is first rendered. There are multiple ways to achieve this, but one would be to use the onSelect
callback to keep some state regarding which tabs have already rendered, and apply the forceRender
prop to those tabs you want to persist in the DOM once they have rendered. Something like this:
function PostMountPersistedTabs() {
const [renderedPanels, setRenderedPanels] = useState([0]);
const onSelect = useCallback((index) => {
setRenderedPanels((renderedPanels) =>
renderedPanels.includes(index)
? renderedPanels
: renderedPanels.concat(index)
)
}, []);
return (
<Tabs onSelect={onSelect}>
<TabList>
<Tab>0</Tab>
<Tab>1</Tab>
<Tab>2</Tab>
</TabList>
<TabPanel forceRender={renderedPanels.includes(0)}>Panel 0</TabPanel>
<TabPanel forceRender={renderedPanels.includes(1)}>Panel 1</TabPanel>
<TabPanel forceRender={renderedPanels.includes(2)}>Panel 2</TabPanel>
</Tabs>
);
};
Of course this is a very simple example, but the principle stands.
FWIW I think at this point we've had this question come up so many times in various forms that I think it can be argued that react-tabs
should provide this functionality itself, as apparently it's confusing to many people. But for that to happen someone has to do the work of defining the feature, getting consensus on the API, and implementing it.
from react-tabs.
Hi. I'm not sure where you got the idea that memo
will have an effect on how/whether inactive tab panels are rendered. If you want them to be rendered, you can pass the forceRenderTabPanel
prop to <Tabs>
. This is in the README: https://github.com/reactjs/react-tabs#forcerendertabpanel-boolean.
from react-tabs.
@joepvl So you mean react-tabs cache by default if all props
are same on next visit ? Well for me it didn't, the code is above , so whats wrong with the above code such that despite props.question
being exactly same it's still re-rendering ?
P1QueryTab
looks like this:
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
import 'react-tabs/style/react-tabs.css';
import { memo, useCallback, useState } from 'react'
function P1QueryTab(props: Props) {
let answer = some_external_api(props.question)
return (
<div>{props.question}/></div>
<div>{answer}/></div>
)
}
export default P1QueryTab
I don't want to call some_external_api
again if the props.question
passed to the tab remains same.
from react-tabs.
The data above is over simplified. I posted the same question on stackoverflow with exact data; there folks have blamed the library saying that it doesn't hide the tab by css but removes it totally from the dom tree.
I think your answer is fine if I was only rendering props.question
and not answer
.
My understanding was memo
would prevent external api call if all props
are same despite the fact I have in html something that's not a direct prop
.
from react-tabs.
I'm going to assume by "next visit" you mean the next time a TabPanel is selected.
Correct
example-1 and example-2 are both hazardous.
I am surprised why example-1 is the default behaviour and not example-3.
from react-tabs.
I'm going to assume by "next visit" you mean the next time a TabPanel is selected.
Correctπ
example-1 and example-2 are both hazardous.
I am surprised why example-1 is the default behaviour and not example-3.
Thank you . Great illustration. π
from react-tabs.
One doubt I still have, your example-3 will always render it once irrespective of what prop
I pass to each TabPanel
. right?
Say I start with tab-1 , then I visit tab-2 and then I come back to tab-1 ; this time tab-1 will not rerender. right?
But I may need to re-render if my activities on tab-2 have led to change of props
passed to tab-1 on next visit. So the decision is not only based on "if it was rendered earlier or not" but also based on "if it was rendered earlier with exact same props or not". So essentially I will have to maintain the questions
for each of the 3 tabs instead of just indices of renderedPanels
at the parent level. Dealing with lots of variables and their logic within onSelect
makes approach very untidy which is why I was looking for some out of the box memorization based of function arguments. Will get back to you after combining forceRender
with memo
. Let's see.
from react-tabs.
Related Issues (20)
- Property 'tabsRole' is missing in type 'ReactElement<any, any>' but required in type 'ReactTabsFunctionComponent<TabProps> HOT 1
- No content after refresh HOT 5
- about prop types
- UncontrolledTabs.js Eror: Uncaught TypeError: (0 , react__WEBPACK_IMPORTED_MODULE_0__.useId) is not a function HOT 5
- keyboard accessibility of https://reactcommunity.org/react-tabs/ HOT 5
- React-tabs closes React-select (onclick)
- Issues when implementing the same Tabs for different TabPanels HOT 2
- export 'useId' (imported as 'useId') was not found in 'react' HOT 2
- Possible to disable using TabPanel when in controlled mode? HOT 1
- How I can fix this error in react version dependency? HOT 2
- Components Rendering Issue HOT 3
- typo
- React-tabs dropped clicks on tab switch when inspecting on mobile device HOT 1
- defaultProps warning - Support for defaultProps will be removed from function component will be removed HOT 5
- Could not find a declaration file for module 'react-tabs' on v4.2.1 HOT 2
- Disabled tabs should remain keyboard focusable as per W3C WAI ARIA guidelines HOT 3
- Support hiding of all TabPanels HOT 1
- How to set the tab container's width to be the width of the widest tab? HOT 1
- Errors when using react-tabs in an Astro page
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from react-tabs.