Реагировать — взаимодействовать между компонентами пользовательского интерфейса Material

#reactjs #material-ui

#reactjs #материал-пользовательский интерфейс

Вопрос:

Я использую компонент Material UI nested / select ItemList для динамической генерации любого количества элементов выпадающего меню на основе того, сколько элементов принадлежит этому заголовку, как вы, возможно, можете определить из функции сопоставления. В другом файле на 1 уровень выше этого я снова сопоставляю и генерирую несколько из этих выпадающих меню, возможно ли, чтобы эти компоненты взаимодействовали друг с другом?

Это файл, о котором идет речь

 const useStyles = makeStyles((theme) => ({
  root: {
    width: '100%',
    maxWidth: 330,
    backgroundColor: theme.palette.background.paper,
  },
  nested: {
    paddingLeft: theme.spacing(4),
  }
}));

export default function DropDownMenu(props) {
  const classes = useStyles();
  const [open, setOpen] = React.useState(true);
  
  let unitName = props.unit[0];
  let chapterList = props.unit.slice(1);

  const [selectedIndex, setSelectedIndex] = React.useState(1);

  const handleListItemClick = (index) => {
    console.log("ItemClicked");
    console.log(index);
    setSelectedIndex(index);
  };

  const handleClick = () => {
    setOpen(!open);
  };

  const selectMenuItem = (chapter, index) => {
    props.chooseChapter(chapter)
    handleListItemClick(index)
  }


  let dropDownUnit = chapterList.map((chapter, index) => {
    return (
        <ListItem button 
        className={classes.selected}
        selected={selectedIndex === index}
        onClick={() => selectMenuItem(chapter, index)}
        key={index}>
          <ListItemText primary={chapter} />
        </ListItem>
    )
  })

  return (
    <List
      component="nav"
      aria-labelledby="nested-list-subheader"
      subheader={
        <ListSubheader component="div" id="nested-list-subheader">
        </ListSubheader>
      }
      className={classes.root}
    >
      <ListItem button onClick={handleClick}>
        <ListItemText primary={unitName} />
        {!open ? <ExpandLess /> : <ExpandMore />}
      </ListItem>
      <Collapse in={!open} timeout="auto" unmountOnExit>
        <List component="div" disablePadding className={classes.selected}>
          {dropDownUnit}
        </List>
      </Collapse>
    </List>
        
  );
}
  

Стиль Psudo — чего я пытаюсь достичь

 <DropDownMenu>
   <MenuItem>  // Suppose this is selected
   <MenuItem>
<DropDownMenu>
   <MenuItem>  // onClick --> Select this and deselect all other selected buttons
  

Ответ №1:

У вас может быть родительский элемент этих компонентов, чтобы родительский элемент сохранял состояние того, кто активен. Таким образом, вы можете передать это состояние и установщик состояния в качестве реквизита, чтобы все знали, кто активен

 export default function App() {
  const [selectedItem, setSelectedItem] = React.useState();

  return (
    <>
      <DropDownMenu
        selectedItem={selectedItem} // pass down as props
        setSelectedItem={setSelectedItem} // pass down as props
        unit={...}
        chooseChapter={function () {}}
      />
      ...
  

Для дочерних элементов просто реорганизуйте Призыв к действию (в данном случае onClick ), чтобы установить состояние, используя переданные реквизиты. Обратите внимание на selected реквизит ListItem , теперь мы используем состояние, которое мы передали от родительского

 let dropDownUnit = chapterList.map((chapter, index) => {
  return (
    <ListItem
      button
      className={classes.selected}
      selected={props.selectedItem === chapter}
      onClick={() => props.setSelectedItem(chapter)}
      key={index}
    >
      <ListItemText primary={chapter} />
    </ListItem>
  );
});
  

Редактировать снежно-фиолетовый-e8d82

Комментарии:

1. Да, хотя мне пришлось немного подправить код, чтобы он соответствовал моей специфике, это помогло мне понять, что мне нужно сделать, чтобы заставить его работать. Спасибо!