J'ai un projet WebGL/React qui génère une liste d'utilisateurs à partir d'une simulation de données sur clic.
Je veux que ce contenu apparaisse dans un accordéon et, comme j'ai eu une bonne expérience avec l'interface matérielle avant de penser que j'utiliserais leur panneau d'extension.
Cela fonctionne bien directement à partir de la page de démonstration, mais si je voulais mapper sur ma base de données utilisateur et remplir les panneaux d'extension avec cela à la place, cela semble me débarrasser de la fonctionnalité pratique.
Je voudrais que le premier panneau d'extension s'ouvre par défaut, puis lorsque vous cliquez sur un panneau, tous les autres panneaux se ferment, ce qui est le comportement par défaut de l'exemple.
Quand je passe dans les accessoires
<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>
alors utilisez-le ici ....
{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>
))}
Il ouvre tous les panneaux par défaut et ne ferme pas les autres quand l'un est actif. (encore une fois, pas de données réelles et le gif le rend un peu bogué mais je ne peux pas générer d'exemple car la base de code est trop énorme).
Quelqu'un aurait-il des idées ou des exemples sur la façon d'y parvenir?
ÉDITER
selon la suggestion ci-dessous, ont ajouté un identifiant dans la fonction de mappage et adapté le composant d'extension, obtenant malheureusement le même effet/problèmes
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>
);
}```
Difficile de dire ce que vous faites avec ExpansionPanel, mais il semblerait que vous ayez le même
<ExpansionPanel expanded={expanded === 'panel1'} onChange={handleChange('panel1')}>
pour chacun d'entre eux, vous devez avoir des noms uniques (panel1, panel2, panel3) pour eux.
MODIFIER:
Vous pouvez ajouter un itérateur dans la fonction de carte:
users.map((user, i) => (
et ai-je passé au ExpansionPanel comme accessoire pour
<ExpansionPanel expanded={expanded === 'panel' + props.i} onChange={handleChange('panel' + props.i)}>
EDIT # 2: réponse mise à jour avec code fonctionnel et raison pour laquelle le vôtre n'a pas fonctionné.
Fonction principale, notez que vous devez ajouter ici useState et les donner à l'enfant CustomizedExpansionPanels.
exemple.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>
)
}
Difficile à dire avec certitude, mais il semble que vous bouclez la création d'un seul et même panneau où le crochet étendu existe dans chacun d'eux et a la valeur id de son propre panneau => non lié à l'ouverture et à la fermeture des autres panneaux . Vous devez créer chaque ExpansionPanel avec ses propres variables et avoir 1 hook pour les contrôler tous.