I have WebGL/React project that generates a list of users from a mock data on click.
I want this content to appear in an accordion and, as I've had good experience with material ui before I thought I'd use their expansion panel.
It works well straight from the demo page, however if I wanted to map over my user data base and populate the expansion panels with this instead, it appears to get rid of the handy functionality.
I would like the first expansion panel open by default and then as you click on one panel, any other panels close, which is the default behaviour from the example.
When I pass in props
<ExpansionPanel
square
expanded={expanded === "panel1"}
onChange={handleChange("panel1")}
>
<ExpansionPanelSummary
aria-controls="panel1d-content"
id="panel1d-header"
>
{props.country}
</ExpansionPanelSummary>
<ExpansionPanelDetails>{props.children}</ExpansionPanelDetails>
</ExpansionPanel>
</div>
then use it here....
{users &&
users.map(user => (
<Accordion title={user.name} key={user.name}>
<div className="overlay-container">
<div className="overlay overlay-anim">
<div className="overlay-content-container">
<div className="name-container">
<h1 key={user.id} className="user_name">
{user.name}
</h1>
</div>
</div>
</div>
</div>
</Accordion>
))}
It opens all the panels by default and doesn't close the others when one is active. (again not real data and the gif makes it a little buggy but I can't generate an example as the code base is too huge).
Would anyone have some ideas or examples of how to achieve this?
EDIT
as per below suggestion have added added an id into the mapping function and adapted the expansion ponent, unfortunately getting the same effect/issues
const [expanded, setExpanded] = React.useState("panel" + props.id);
const handleChange = panel => (event, newExpanded) => {
setExpanded(newExpanded ? panel : false);
};
return (
<div>
<ExpansionPanel
expanded={expanded === "panel" + props.i}
onChange={handleChange("panel" + props.i)}
>
<ExpansionPanelSummary
aria-controls={"panel" + props.id + "d" + "-content"}
id={"panel" + props.id + "d" + "-header"}
>
{props.country}
</ExpansionPanelSummary>
<ExpansionPanelDetails>{props.children}</ExpansionPanelDetails>
</ExpansionPanel>
</div>
);
}```
I have WebGL/React project that generates a list of users from a mock data on click.
I want this content to appear in an accordion and, as I've had good experience with material ui before I thought I'd use their expansion panel.
It works well straight from the demo page, however if I wanted to map over my user data base and populate the expansion panels with this instead, it appears to get rid of the handy functionality.
I would like the first expansion panel open by default and then as you click on one panel, any other panels close, which is the default behaviour from the example.
When I pass in props
<ExpansionPanel
square
expanded={expanded === "panel1"}
onChange={handleChange("panel1")}
>
<ExpansionPanelSummary
aria-controls="panel1d-content"
id="panel1d-header"
>
{props.country}
</ExpansionPanelSummary>
<ExpansionPanelDetails>{props.children}</ExpansionPanelDetails>
</ExpansionPanel>
</div>
then use it here....
{users &&
users.map(user => (
<Accordion title={user.name} key={user.name}>
<div className="overlay-container">
<div className="overlay overlay-anim">
<div className="overlay-content-container">
<div className="name-container">
<h1 key={user.id} className="user_name">
{user.name}
</h1>
</div>
</div>
</div>
</div>
</Accordion>
))}
It opens all the panels by default and doesn't close the others when one is active. (again not real data and the gif makes it a little buggy but I can't generate an example as the code base is too huge).
Would anyone have some ideas or examples of how to achieve this?
EDIT
as per below suggestion have added added an id into the mapping function and adapted the expansion ponent, unfortunately getting the same effect/issues
const [expanded, setExpanded] = React.useState("panel" + props.id);
const handleChange = panel => (event, newExpanded) => {
setExpanded(newExpanded ? panel : false);
};
return (
<div>
<ExpansionPanel
expanded={expanded === "panel" + props.i}
onChange={handleChange("panel" + props.i)}
>
<ExpansionPanelSummary
aria-controls={"panel" + props.id + "d" + "-content"}
id={"panel" + props.id + "d" + "-header"}
>
{props.country}
</ExpansionPanelSummary>
<ExpansionPanelDetails>{props.children}</ExpansionPanelDetails>
</ExpansionPanel>
</div>
);
}```
Share
Improve this question
edited Feb 5, 2020 at 15:35
LAT89
asked Feb 5, 2020 at 11:08
LAT89LAT89
1714 silver badges15 bronze badges
1 Answer
Reset to default 3Hard to say what you are doing with the ExpansionPanel, but it would appear you have same
<ExpansionPanel expanded={expanded === 'panel1'} onChange={handleChange('panel1')}>
for everyone of them, you need to have unique names (panel1, panel2, panel3) for them.
EDIT:
You could add iterator into the map function:
users.map((user, i) => (
and have i passed to the ExpansionPanel as prop for
<ExpansionPanel expanded={expanded === 'panel' + props.i} onChange={handleChange('panel' + props.i)}>
EDIT #2: updated answer with working code and reason why yours didn't work.
Main function, note that u should add the useState here and give them to the CustomizedExpansionPanels child.
example.jsx
import React, { useState } from 'react'
import { withStyles } from '@material-ui/core/styles'
import CustomizedExpansionPanels from './TestTab.jsx'
const styles = (theme) => ({
/* ... your styles... */
})
const users = [
{ name: '5001', color: 'green', type: 'None' },
{ name: '5002', color: 'blue', type: 'Glazed' },
{ name: '5003', color: 'red', type: 'Chocolate' },
{ name: '5004', color: 'orange', type: 'Maple' }
]
function Example(props) {
const [expanded, setExpanded] = useState('panel_0') // change 0 to the number u want to be open by default
return (
<div>
{users.map((user, i) => CustomizedExpansionPanels(user, i, expanded, setExpanded))}
<div/>
)
export default withStyles(styles, { withTheme: true })(Example)
TestTab.jsx
import React from 'react'
import { withStyles } from '@material-ui/core/styles'
import MuiExpansionPanel from '@material-ui/core/ExpansionPanel'
import MuiExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary'
import MuiExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails'
import Typography from '@material-ui/core/Typography'
const ExpansionPanel = withStyles({
root: {
border: '1px solid rgba(0, 0, 0, .125)',
boxShadow: 'none',
'&:not(:last-child)': {
borderBottom: 0,
},
'&:before': {
display: 'none',
},
'&$expanded': {
margin: 'auto',
},
},
expanded: {},
})(MuiExpansionPanel)
const ExpansionPanelDetails = withStyles((theme) => ({
root: {
padding: theme.spacing(2),
},
}))(MuiExpansionPanelDetails)
const ExpansionPanelSummary = withStyles({
root: {
backgroundColor: 'rgba(0, 0, 0, .03)',
borderBottom: '1px solid rgba(0, 0, 0, .125)',
marginBottom: -1,
minHeight: 56,
'&$expanded': {
minHeight: 56,
},
},
content: {
'&$expanded': {
margin: '12px 0',
},
},
expanded: {},
})(MuiExpansionPanelSummary)
export default function CustomizedExpansionPanels(user, id, expanded, setExpanded) {
const handleChange = (panel) => (event, newExpanded) => {
setExpanded(newExpanded ? panel : false)
}
const { name, color, type } = user
return (
<div>
<ExpansionPanel square expanded={expanded === `panel_${id}`} onChange={handleChange(`panel_${id}`)}>
<ExpansionPanelSummary aria-controls={`panel_${id}d-content`} id={`panel_${id}d-header`}>
<Typography style={{ color }}>{`Collapsible Group Item #${id}`}</Typography>
</ExpansionPanelSummary>
<ExpansionPanelDetails>
<Typography>
{`name: ${name} type: ${type}`}
</Typography>
</ExpansionPanelDetails>
</ExpansionPanel>
</div>
)
}
Hard to say for sure, but it looks like you are looping the creation of one and same panel where the extended hook exists in each one of them and has the value id of it's own panel => not related to the other panels opening and closing. You need to create each ExpansionPanel with it's own variables and have 1 hook to control them all.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745331860a4622918.html
评论列表(0条)