web-dev-qa-db-fra.com

Comment ajouter du contenu dynamique aux React Panneaux d'extension de l'interface utilisateur matérielle tout en ne conservant qu'un seul onglet actif à la fois)

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.

Material ui example

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).

enter image description here

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>
  );
}```
5
LauraAnnabel89

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.

1
btnhawk