Как провести рефакторинг материала-демо, который делится информацией о теме - PullRequest
1 голос
/ 14 октября 2019

Я использую следующий пример кода для рамки вокруг небольшого приложения:

https://material -ui.com / components / drawers / # MiniDrawer.js

При попытке реорганизовать элементы в отдельные компоненты я столкнулся с проблемой. Резка и вставка кода в совершенно новое приложение create-react-app отлично работает. Однако, как только я пытаюсь преобразовать AppBar и Drawer в отдельные компоненты, я подозреваю, что они теряют связь друг с другом.

Моя версия для codesandbox.io.

Я начал с извлечения useStyles в отдельный файл:

// useStyles.js
import { makeStyles } from '@material-ui/core/styles';

const drawerWidth = 240;

const useStyles = makeStyles(theme => ({
  root: {
    display: 'flex',
  },
  appBar: {
    zIndex: theme.zIndex.drawer + 100,
    transition: theme.transitions.create(['width', 'margin'], {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.leavingScreen,
    }),
  },
  appBarShift: {
    marginLeft: drawerWidth,
    width: `calc(100% - ${drawerWidth}px)`,
    transition: theme.transitions.create(['width', 'margin'], {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.enteringScreen,
    }),
  },
  menuButton: {
    marginRight: 36,
  },
  hide: {
    display: 'none',
  },
  drawer: {
    width: drawerWidth,
    flexShrink: 0,
    whiteSpace: 'nowrap',
  },
  drawerOpen: {
    width: drawerWidth,
    transition: theme.transitions.create('width', {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.enteringScreen,
    }),
  },
  drawerClose: {
    transition: theme.transitions.create('width', {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.leavingScreen,
    }),
    overflowX: 'hidden',
    width: theme.spacing(7) + 1,
    [theme.breakpoints.up('sm')]: {
      width: theme.spacing(9) + 1,
    },
  },
  toolbar: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'flex-end',
    padding: theme.spacing(0, 1),
    ...theme.mixins.toolbar,
  },
  content: {
    flexGrow: 1,
    padding: theme.spacing(3),
  },
}));

export default useStyles;

. .. и AppBar и Drawers в свои собственные файлы:

// MyUIAppBar.js
import React from 'react';
import clsx from 'clsx';
// ...

import { Mail, Notifications, Menu } from '@material-ui/icons';

function MyUIAppBar(props) {

  const classes = props.classes;
  const toggleDrawer = props.toggleDrawer;
  const open = props.open;

  return(
    <AppBar
    position="fixed"
    className={clsx(classes.appBar, {
      [classes.appBarShift]: open,
    })}
  >
    <Toolbar>
      <IconButton
        color="inherit"
        aria-label="open drawer"
        onClick={toggleDrawer}
        edge="start"
        className={clsx(classes.menuButton, {
          [classes.hide]: open,
        })}
      >
        <Menu />
      </IconButton>
      <Typography component="h1" variant="h6" color="inherit" noWrap className={classes.title}>
        MDS MyUI
      </Typography>

      // ...

    </Toolbar>
  </AppBar>
);
}

export default MyUIAppBar;

и

// MyUIDrawer.js
import React from 'react';
import clsx from 'clsx';
import Drawer from '@material-ui/core/Drawer';
import IconButton from '@material-ui/core/IconButton';
import { ChevronLeft, ChevronRight } from '@material-ui/icons';

function MyUIDrawer(props) {

  const classes = props.classes;
  const toggleDrawer = props.toggleDrawer;
  const open = props.open;

  return (
    <Drawer
      variant="permanent"
      className={clsx(classes.drawer, {
        [classes.drawerOpen]: open,
        [classes.drawerClose]: !open,
      })}
      classes={{
        paper: clsx({
          [classes.drawerOpen]: open,
          [classes.drawerClose]: !open,
        }),
      }}
      open={open}
      onToggle={toggleDrawer}
    >
      <div className={classes.toolbar}>
        <IconButton onClick={toggleDrawer}>
          {open ? <ChevronRight /> : <ChevronLeft />}
        </IconButton>
      </div>
      {props.children}
    </Drawer>
  );
}

export default MyUIDrawer;

, а в основном файле приложения я должен был передать theme, open, classes иtoggleDrawer в качестве реквизита для обоих компонентов:

// App.js
import React from 'react';
import useStyles from './styles';
import WebUIDrawer from './components/WebUIDrawer';
import WebUIAppBar from './components/WebUIAppBar';
import { useToggle } from './hooks';
import { useTheme } from '@material-ui/core/styles';
// ... various imports here

export default function App() {
  const classes = useStyles();
  const theme = useTheme();
  const [ open, toggleDrawer ] = useToggle(true);

  return (
    <div className={classes.root}>
      <CssBaseline />
      <WebUIAppBar theme={theme} open={open} classes={classes} toggleDrawer={toggleDrawer}/>
      <WebUIDrawer open={open} classes={classes} toggleDrawer={toggleDrawer} >
        <List>
          {['Eeny', 'Meeny', 'Miney', 'Mo'].map((text, index) => (
            <ListItem button key={text}>
              <ListItemIcon>{index % 2 === 0 ? <MoveToInbox /> : <Mail />}</ListItemIcon>
              <ListItemText primary={text} />
            </ListItem>
          ))}
        </List>
      </WebUIDrawer>
      <Main classes={classes}/>
    </div>
  );
}

Результат вроде работает, но, похоже, есть проблема с наложением и смещением меню. Я подозреваю, что как-то тема не обновляется между ними. Есть ли лучший способ поделиться информацией о стиле между компонентами? Можно ли использовать контекст React для этого? Честно говоря, я в тупике. : - (

1 Ответ

1 голос
/ 14 октября 2019

Основной проблемой является местоположение вашего импорта useStyles. Он должен быть последним, чтобы убедиться, что определяемые им стили помещены после стилей по умолчанию в <head>. См. В этом связанном ответе подробности о том, почему: Материал UI v4 makeStyles, экспортированные из одного файла, не сохраняют стили при обновлении .

Вот исправленная версия вашей песочницы: https://codesandbox.io/s/fixed-usestyles-import-q0m8z.

Все, что я сделал, это переместил импорт useStyles в App.js.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...