javascript - How to add dynamic content to React Material UI expansion panels whilst keeping only one active tab at at time func

I have WebGLReact project that generates a list of users from a mock data on click.I want this content

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
Add a ment  | 

1 Answer 1

Reset to default 3

Hard 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条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信