我刚开始使用 Material-UI
。我知道我可以在组件中使用 createStyles
来设置其样式,并且我还可以使用 createMuiTheme
创建全局主题。我想做的是以 createMuiTheme
方式创建一个主题,并包含许多不同的主色和辅助色组合。
我正在制作一个显示 NHL 球队统计数据的网络应用程序。我正在动态创建一个组件,该组件根据 React-Router
和页面 URL 显示团队统计信息。例如,如果用户访问 /rangers
,则页面显示纽约游骑兵队统计数据,如果用户访问 /bruins
,则页面显示波士顿棕熊队统计数据,等等...
我实现这一点的方法是使用React-Router的
useLocation功能。当用户导航到 /rangers
时,我使用 useLocation
从 URL 中获取 rangers
并将团队名称放入 GET 请求中,以便 Rangers请求并显示统计信息。
我想做的是创建一个 Material-UI
主题,以根据所属团队动态设置页面上的主要颜色和次要颜色。例如,当用户位于 /rangers
(流浪者队颜色)时,我想将主要颜色设置为蓝色,次要颜色设置为红色。如果用户要导航到 /bruins
那么我想将主要颜色和次要颜色设置为 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'
}
});
有没有一种方法可以根据 React-Router
所在的页面在 Material-UI
中动态设置主题颜色,即导航到 /rangers
> 设置 Rangers 颜色并导航到 /bruins
在主题中设置 Bruins 颜色?我想以与执行 GET 请求类似的方式使用 useLocation
来实现此目的。
我有 31 个不同的团队/页面,因此动态执行此操作比手动创建具有不同样式的 31 个不同组件要高效得多。
最佳答案
您可以创建一种修改主题的方法。在这种情况下,我们需要了解如何在组件树中渲染组件。不过,我做了一个简单的操作示例,您可以将其作为您实现的基础。
从技术上讲,您需要使用 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]);
希望对您有所帮助。
关于css - React-Router 和 Material-UI : Applying custom themes depending on route,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61600091/