我刚开始使用Material-UI
。我知道我可以在组件内使用createStyles
对其进行样式设置,也可以使用createMuiTheme
创建全局主题。我想做的是以createMuiTheme
方式创建主题,并包含许多不同的原色和第二色组合。
我正在制作一个显示NHL团队统计信息的Web应用程序。我正在动态创建一个基于React-Router
和页面URL显示团队统计信息的组件。例如,如果用户转到/rangers
,则该页面显示“纽约流浪者”的统计信息;如果用户转到/bruins
,则该页面显示“波士顿熊”的统计信息,等等。
我完成此操作的方法是使用React-Router's
useLocation函数。当用户导航到/rangers
时,我使用useLocation
从URL中抓取rangers
,然后将团队名称放入GET请求中,以便请求并显示Rangers统计信息。
我想做的是创建一个Material-UI
主题,以根据页面所属的团队在页面上动态设置原色和副色。例如,当用户在/rangers
时,我想将原色设置为蓝色,将次要颜色设置为红色(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'
}
});
是否有一种方法可以根据Material-UI
所在的页面在React-Router
中动态设置主题颜色,即导航至/rangers
设置流浪者的颜色并导航至/bruins
的设置主题中的棕褐色?我想以与我执行GET请求类似的方式使用useLocation
。
我有31个不同的团队/页面,所以动态地执行此操作比手动创建31个具有不同样式的不同组件要有效得多。
答案 0 :(得分:2)
您可以创建一种修改主题的方法。在这种情况下,我们需要了解如何在组件树中渲染组件。但是,我给出了一个简单的操作示例,您可以将其作为实现的基础。
从技术上讲,您需要使用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]);
我希望这会有所帮助。