Consider the following code snippet of a component:
...
...
function a11yProps(index: any) {
return {
id: `simple-tab-${index}`,
'aria-controls': `simple-tabpanel-${index}`,
};
}
...
...
return (
<div className={classes.root}>
<AppBar position="static">
<Tabs value={value} onChange={handleChange} aria-label="simple tabs example">
<Tab label="Item One" {...a11yProps(0)} />
<Tab label="Item Two" {...a11yProps(1)} />
<Tab label="Item Three" {...a11yProps(2)} />
</Tabs>
</AppBar>
<TabPanel value={value} index={0}>
Item One
</TabPanel>
<TabPanel value={value} index={1}>
Item Two
</TabPanel>
<TabPanel value={value} index={2}>
Item Three
</TabPanel>
</div>
);
}
I struggle to understand the following component implementation:
<Tab label="Item One" {...a11yProps(0)} />
What does {...a11yProps(0)} mean? Does it mean I pass here properties?
When I look at the API documentation of Tab, I can not find the id and aria-controls properties.
The whole code https://codesandbox.io/s/kz25m
It is a spread operator (... is Javascript spread operator). It basically de-structures / spreads out the value from an array or object.
In your sample code I see your function returns some javascript object. This spread operator pulls out / de-structures all the values from the object and gives each individual values as output
{... a11yProps(0)}
==> This would return -> {...{id: `simple-tab-0`,aria-controls: `simple-tabpanel-0`}}
==> on spreading out the values from the object it would look like
=> {id: `simple-tab-0`,aria-controls: `simple-tabpanel-0`}
Another example with spread operator
let d = {...{"a":1, "b":2, "c":3}}
output: {a: 1, b: 2, c: 3}
Please refer to ES6 website for more on spread operator, destructuring - http://es6-features.org/#SpreadOperator
It's just a function for making a dynamic object and using them as props, to reduce code size.
<Tab label="Item One" id="simple-tab-0" ariaControls="simple-tabpanel-0"/>
About TypeScript and Docs: If you ctrl + click on the Material-UI component, you can see they extends types of component with React.ElementType and inside of this, you can find JSX.IntrinsicElements and each one of HTML element has React.DetailedHTMLProps with props of HTMLAttributes extended with AriaAttributes and DOMAttributes. So naturally, you can pass all of the available attributes for that tag on them!
Related
I'm using chakra-ui to build a web app, in which I have three tabs, each with their own state. The state of each tab should be shared between all the other tabs. But if I lift up all the states to the parent and pass them as props to each tab, it gets laggy because every time I change something in a tab, it rerenders everything.
Are there other ways to share data between them or, if only lift state up works, prevent rerender of inactive tabs?
<Tabs>
<TabList>
<Tab>Cálculos</Tab>
<Tab>Gráficos</Tab>
<Tab>Resultados</Tab>
</TabList>
<Stack direction='row'>
<TabPanels >
<TabPanel m={0} p={0} w='full' h='full'>
<Calculations testStarted={testStarted} />
</TabPanel>
<TabPanel m={0} p={0} w='full' h='full'>
<Graphics testStarted={testStarted} />
</TabPanel>
<TabPanel m={0} p={0} w='full' h='full'>
<Results testStarted={testStarted} />
</TabPanel>
</TabPanels>
</Stack>
</Tabs>
You can use useContext
React Beta docs has a good visual tutorial on this:
https://beta.reactjs.org/learn/passing-data-deeply-with-context
Still relatively new to Material UI and ReactJS.
But I'm trying to have a set of tabs at the top of the page, but I also want a Logout link to the right side of the tabs.
Here's what I have
<AppBar position="static">
<Tabs
value={value}
onChange={handleChange}
aria-label="simple tabs example"
style={{flex:1}}
>
<Tab label="Approvals" />
<Tab label="Members" />
</Tabs>
Logout
</AppBar>
But the logout link isn't aligned to the right and is on a new line underneath the Tabs.
How would I go about having it sit at the end of the tabs?
I think it can help you. Add between and Logout button.
<AppBar position="static">
<Toolbar>
<Tabs
value={value}
onChange={handleChange}
aria-label="simple tabs example"
>
<Tab label="Approvals" />
<Tab label="Members" />
</Tabs>
<Box flexGrow={1} />
<Button>Logout</Button>
</Toolbar>
</AppBar>
I am new to React. I am using React web tabs to create tabs in react.
How would one go about triggering a change of tab panels upon clicking a button element, I have two button, "Previous" & "Next". On click of previous button , i want to go to previous tab & On next button click it should show next tab ?
<Tabs defaultTab="one" vertical className="vertical-tabs" selectedIndex={this.state.selectedTabIndex}
onSelect={this.handleSelect}>
<TabList>
<Tab tabFor="one" >BASIC INFORMATION</Tab>
<Tab tabFor="two" >ADVANCED INFORMATION</Tab>
<Tab tabFor="three">ASSIGN USERS</Tab>
<Tab tabFor="four" >TEMPLATE</Tab>
</TabList>
<TabPanel tabId="one">
//BASIC INFORMATION
</TabPanel>
<TabPanel tabId="two">
//ADVANCED INFORMATION
</TabPanel>
<TabPanel tabId="three">
//ASSIGN USERS
</TabPanel>
<TabPanel tabId="four">
//TEMPLATE
</TabPanel>
{
<div>
<Button onClick={()=>this.handlePreviousBtnChange()}>Back</Button>
</div>}{<div>
<Button onClick={()=>this.handleNextBtnChange()}>Next</Button>
</div>}
</Tabs>
Please help me.Thanks in advance
According to this closed issue on the project, you should be able to use defaultTab to programmatically change the selected tab. https://github.com/marcuslindfeldt/react-web-tabs/issues/10#issuecomment-482846520
Here's a short example. I made the tab ids numbers to make incrementing/decrementing easier.
const ControllableTabs = () => {
const [selectedTab, setSelectedTab] = useState(0);
const tabCount = 3;
return (
<>
<Tabs defaultTab={selectedTab.toString()}>
<TabList>
<Tab tabFor="0">Tab 1</Tab>
<Tab tabFor="1">Tab 2</Tab>
<Tab tabFor="2">Tab 3</Tab>
</TabList>
<TabPanel tabId="0">
<p>Tab 1 content</p>
</TabPanel>
<TabPanel tabId="1">
<p>Tab 2 content</p>
</TabPanel>
<TabPanel tabId="2">
<p>Tab 3 content</p>
</TabPanel>
</Tabs>
<Button onClick={() => setSelectedTab((selectedTab + tabCount - 1) % tabCount )}>Back</Button>
<Button onClick={() => setSelectedTab((selectedTab + 1) % tabCount )}>Next</Button>
</>
);
}
I should note that there are other libraries that possibly suit your needs better, depending on the functionality that you desire. If you happen to be using material-ui in your project already, the Stepper component provides much more customizability. https://material-ui.com/components/steppers/#stepper
App.jsx is:
<ThemeProvider theme={theme}>
<div>
<Tabs index={0}>
<Tab label='Primary'><small>1Primary content</small></Tab>
<Tab label='Secondary'><small>Sec content</small></Tab>
</Tabs>
<Input label="test"/>
</div>
</ThemeProvider>
Error:
TypeError: Cannot read property 'pointer' of undefined Tabs.render #
line 240 var classNamePointer = (0,
_classnames4.default)(theme.pointer, _defineProperty({}, theme.disableAnimation, disableAnimatedBottomBorder));
Yo should add forceRenderTabPanel={true} to the tabs as such: .
It will keep track of the state across all three tabs and not just the one you are on.
Using material-ui I'm attempting to iterate an array and render a item value as a tab. I'd like to have the tabs grow on load as per this example https://material-ui.com/utils/transitions/#grow.
I'm able to effectively do the iteration and show the tabs as follows;
<Tabs fullWidth value={value} onChange={this.handleChange} scrollable>
{this.props.myArray.map((p, i) =>
<Tab value={p.value} label={`${p.value}`}/>)}
</Tabs>
The logical approach would be;
<Tabs fullWidth value={value} onChange={this.handleChange} scrollable>
{this.props.myArray.map((p, i) =>
<Grow in={true} timeout={500}
<Tab value={p.value} label={`${p.value}`}/>
</Grow>)}
</Tabs>
But this does not work, "p" becomes inaccessible and it does not apply the Grow effect.
Is my best option to use the Tab source and create my own component that implements a transition as outlined here https://reactcommunity.org/react-transition-group/transition?
I'm happy to do this, but would obviously prefer the above method if there is a simple solution.
Thanks!