reactjs - 从 onClick 事件进行 api 调用后在运行时更改应用程序主题
问题描述
我是 next.js 的新手,我会做出反应并且无法解决这个问题。我的应用程序要求我在进行 api 调用后在运行时更改页面的整个主题。我正在使用 next.js 反应和材料 UI。
我试图做的是创建一个反应上下文并在其中一个嵌套子项中使用它,但不幸的是我不能在 onClick 函数中使用它,这违背了我想要做的事情的目的。
理想流量
- 在 _app.ts 中声明一个主题对象作为 ThemeProvider 的参数
- 在其中一个页面的按钮中有一个 onClick 事件,该事件将对 api 进行异步调用并检索颜色值
- 根据该值创建主题对象
- 将应用程序主题交换为新主题。
到目前为止我得到的是这个,但它看起来很笨重。
export default function MyApp(props: any) {
const { Component, pageProps } = props;
const [theme, setTheme] = useState(muiTheme);
const value = { theme, setTheme };
React.useEffect(() => {
// Remove the server-side injected CSS.
const jssStyles = document.querySelector('#jss-server-side');
if (jssStyles && (jssStyles.parentElement !== null)) {
jssStyles.parentElement.removeChild(jssStyles);
}
}, []);
return (
<React.Fragment>
<Head>
<title>My page</title>
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
</Head>
<ThemeProvider theme={value.theme}>
// IS THERE A WAY NOT TO USE MY OWN ThemeContext.Provider and use MUI Theme provider instead to change a theme?
<ThemeContext.Provider value={value}>
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
<CssBaseline />
<Component {...pageProps} />
</ThemeContext.Provider>
</ThemeProvider>
</React.Fragment>
);
}
现在在 nextjs 的一个页面中,我有一个按钮,可以在 updateRoom 方法中进行 api 调用。但是在该函数内部,我无法使用 useContext 挂钩。
有没有更好的方法来解决这个问题?
<Button
onClick={() => updateRoom(room, flowActionId)}
...
我想在 updateRoom 方法中做的是这个
async function updateRoom(room: any, flowActionId: any) {
try {
const response = await axios.put(`/api/room/${room.id}`,
{
flow_action_id: Number(flowActionId)
});
const leTheme = createTheme({
palette: {
primary: {
main: '#123123', <--- parse my api call and set this color
}
},
});
const { theme, setTheme } = useContext(ThemeContext);
setTheme(leTheme); <--- set the app theme here.
} catch (error) {
console.error(error);
}
}
解决方案
试着看看我的代码。我试着做同样的事情
我已经像这样创建了一个单独的 ThemeContext 文件..
const ThemeContext = createContext();
const ThemeProvide = (props) => {
const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");
const [theme, setTheme] = useState({
primary: "#003e7e",
secondary: "#ADEFD1FF",
type: prefersDarkMode ? "dark" : "light",
background: "#fafafa",
paper: "#ffffff",
});
const themePalette = createMuiTheme({
palette: {
primary: {
main: theme.primary,
},
secondary: {
main: theme.secondary,
},
background: {
default: theme.background,
paper: theme.paper,
},
type: theme.type,
},
});
return (
<ThemeContext.Provider value={[theme, setTheme]}>
<ThemeProvider theme={themePalette}>
<CssBaseline />
{props.children}
</ThemeProvider>
</ThemeContext.Provider>
);
};
export { ThemeContext, ThemeProvide };
现在我用这个 ThemeProvide 组件包装整个 _app.js //注意黑白 ThemeProvider 和 ThemeProvide 组件的区别我相信你可以比我更好地命名它
import { ThemeProvide } from "../state/theme";
const MyApp = ({ Component, pageProps }) => {
useEffect(() => {
const jssStyles = document.querySelector("#jss-server-side");
if (jssStyles) {
jssStyles.parentElement.removeChild(jssStyles);
}
}, []);
return (
<>
<ThemeProvide>
<Component {...pageProps} />
</ThemeProvide>
</>
);
};
export default MyApp;
现在我可以在我的任何页面或组件中使用 ThemeContext
像这样
const [theme,setTheme ] = useContext(ThemeContext)
//Use setTheme to change your Theme
推荐阅读
- .net - 由于访问被拒绝错误而无法启动程序
- maven - 在“Maven->Update project”之后,构建路径中源文件夹的配置已更改
- java - 使用来自 RESTful Web 服务端点调用的响应,以便稍后在其他 Web 服务端点调用中使用
- excel - Excel:OR + VLOOKUP 无法检测到某些值
- java - Kotlin - 我们如何使用 getter 和 setter 访问私有财产?访问方法是否在内部调用?
- c# - 用 override 和 new 关键字覆盖 ToString()
- html - 如何在 html 模板中呈现节点 js 数据?
- python - 尽管缩进正确,但 Python 缩进错误
- swift - 在 ARKit 1.5 中重置会话时删除文本节点
- android - Android 上的硬件加速 H.264/HEVC 视频解码到 OpenGL FBO 或纹理