简体   繁体   English

如何将动态内容添加到 React Material UI 扩展面板,同时一次只保留一个活动选项卡功能

[英]How to add dynamic content to React Material UI expansion panels whilst keeping only one active tab at at time functionality

I have WebGL/React project that generates a list of users from a mock data on click.我有一个 WebGL/React 项目,它在点击时从模拟数据生成用户列表。

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.我希望这些内容出现在手风琴中,因为在我认为我会使用他们的扩展面板之前,我对材料 ui 有很好的经验。

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.我希望第一个扩展面板默认打开,然后当您单击一个面板时,任何其他面板都会关闭,这是示例中的默认行为。

材质ui示例

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). (同样不是真实数据,gif 使它有点问题,但由于代码库太大,我无法生成示例)。

在此处输入图片说明

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 component, unfortunately getting the same effect/issues根据下面的建议,在映射函数中添加了一个 id 并调整了扩展组件,不幸的是得到了相同的效果/问题

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

Hard to say what you are doing with the ExpansionPanel, but it would appear you have same很难说你在用 ExpansionPanel 做什么,但看起来你有同样的

<ExpansionPanel expanded={expanded === 'panel1'} onChange={handleChange('panel1')}>

for everyone of them, you need to have unique names (panel1, panel2, panel3) for them.对于他们中的每个人,您都需要为他们指定唯一的名称(panel1、panel2、panel3)。

EDIT:编辑:

You could add iterator into the map function:您可以将迭代器添加到 map 函数中:

users.map((user, i) => (

and have i passed to the ExpansionPanel as prop for我有没有传递给 ExpansionPanel 作为道具

<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.编辑#2:更新了工作代码的答案以及您的无效代码的原因。

Main function, note that u should add the useState here and give them to the CustomizedExpansionPanels child.主要功能,请注意您应该在此处添加 useState 并将它们提供给 CustomizedExpansionPanels 子项。

example.jsx例子.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测试表.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.很难确定,但看起来您正在循环创建一个相同的面板,其中每个面板中都存在扩展钩子,并且具有自己面板的值 id => 与其他面板的打开和关闭无关. You need to create each ExpansionPanel with it's own variables and have 1 hook to control them all.您需要使用它自己的变量创建每个 ExpansionPanel,并有 1 个钩子来控制它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM