React-Router и Material-UI: применение пользовательских тем в зависимости от маршрута - PullRequest
2 голосов
/ 04 мая 2020

Я новичок в использовании Material-UI. Я знаю, что могу использовать createStyles внутри компонента для его стилизации, а также могу использовать createMuiTheme для создания глобальной темы. Я бы хотел создать тему в стиле createMuiTheme и включить множество различных комбинаций основных и дополнительных цветов.

Я делаю веб-приложение, которое отображает статистику команды НХЛ. Я динамически создаю компонент, который отображает статистику команды на основе React-Router и URL-адреса страницы. Например, если пользователь переходит на /rangers, страница отображает статистику New York Rangers, если пользователь переходит на /bruins, страница отображает статистику Boston Bruins и т.д. c ...

Как я Я выполняю это с помощью функции React-Router's useLocation . Когда пользователь переходит к /rangers, я использую useLocation, чтобы получить rangers из URL-адреса, и вставляю имя команды в запрос GET, чтобы запрашивалась и отображалась статистика Рейнджеров.

Что бы я хотел нужно создать тему Material-UI для динамической установки основных и дополнительных цветов на странице в зависимости от того, какая команда это. Например, я хочу установить основной цвет на синий, а вторичный цвет на красный, когда пользователь имеет /rangers (цвета команды рейнджеров). Если бы пользователь перешел к /bruins, я бы хотел установить первичный и вторичный цвета на цвета команды Брюинза (черный и золотой).

const Theme = createMuiTheme({
    palette: {
        primary: {
          // When at '/rangers` set primary color to Rangers blue
          rangers: '#0038a8',
          // When at '/bruins` set primary color to Bruins gold
          bruins: '#fcb514'
        },
        secondary: {
          // When at '/rangers` set secondary color to Rangers red
          rangers: '#ce1126',
          // When at '/bruins` set secondary color to Bruins black
          bruins: '#111'
        }
    });

Есть ли способ динамически устанавливать цвета темы в Material-UI в зависимости от того, на какой странице React-Router находится, т.е. переход к /rangers устанавливает цвета Рейнджеров, а переход к /bruins устанавливает Bruins цвета в теме? Я хотел бы использовать для этого useLocation аналогично тому, как я выполняю запрос GET.

У меня 31 отдельная команда / страница, поэтому делать это динамически намного эффективнее, чем вручную создавать 31 разных компоненты с разными стилями.

1 Ответ

2 голосов
/ 05 мая 2020

Вы можете создать способ изменить вашу тему. В этом случае нам нужно будет понять, как вы визуализируете компоненты в дереве компонентов. Однако я сделал простой пример работы, который вы можете взять за основу для своих реализаций.

Edit Button

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

export function ThemeProvider(props) {
  const { children } = props;

  const [themeOptions, dispatch] = React.useReducer((state, action) => {
    switch (action.type) {
      case "CHANGE":
        return {
          ...state,
          colors: action.payload.colors || "DEFAULT"
        };
      default:
        throw new Error(`Unrecognized type ${action.type}`);
    }
  }, themeInitialOptions);

  const { colors } = themeOptions;
  const theme = React.useMemo(() => {
    let palette;

    switch (colors) {
      case "RANGERS":
        palette = {
          primary: { main: "#0038a8" },
          secondary: { main: "#ce1126" }
        };
        break;
      case "BRUINS":
        palette = {
          primary: { main: "#fcb514" },
          secondary: { main: "#111" }
        };
        break;
      default:
        palette = {
          primary: { main: "#673ab7" },
          secondary: { main: "#111" }
        };
        break;
    }

    const nextTheme = createMuiTheme({ palette });
    return nextTheme;
  }, [colors]);

  return (
    <MuiThemeProvider theme={theme}>
      <DispatchContext.Provider value={dispatch}>
        {children}
      </DispatchContext.Provider>
    </MuiThemeProvider>
  );
}

Затем предоставить общую точку входа для изменений.

export function useChangeTheme() {
  const dispatch = React.useContext(DispatchContext);
  return React.useCallback(
    themeOptions => dispatch({ type: "CHANGE", payload: themeOptions }),
    [dispatch]
  );
}

Наконец, мы можем использовать его таким образом в компоненте на верхняя часть вашего дерева React.

  const changeTheme = useChangeTheme();
  const location = useLocation();

  React.useEffect(() => {
    let path = location && location.pathname.split("/");
    let team = path && path[1];
    changeTheme({ colors: team.toUpperCase() });
  }, [changeTheme, location]);

Надеюсь, это поможет.

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