如何在Gatsby JS项目中管理状态并将Header的开关状态传递到其他页面
解决方案
方案1:状态提升(适合简单场景,无复杂状态流转)
Gatsby项目通常会有一个全局Layout.js组件,你的Header和各个页面内容都是作为子元素嵌套在这个Layout里的,直接把切换按钮的状态从Header提到Layout层即可:
- 第一步:在Layout组件里定义状态和修改状态的方法
// src/components/Layout.js import React, { useState } from 'react' import Header from './header' const Layout = ({ children }) => { // 把原来在Header里的切换状态移到这里 const [toggleActive, setToggleActive] = useState(false) return ( <div> {/* 把状态和修改方法传给Header */} <Header toggleActive={toggleActive} setToggleActive={setToggleActive} /> {/* 页面内容部分,把状态传递给子页面 */} <main>{React.cloneElement(children, { toggleActive })}</main> </div> ) } export default Layout
- 第二步:修改Header组件,改用Layout传过来的props,不再单独维护状态
// src/components/header.js const Header = ({ toggleActive, setToggleActive }) => { return ( <header> <button onClick={() => setToggleActive(!toggleActive)}> 切换按钮 </button> </header> ) }
- 第三步:业务页面直接从props获取状态即可
// src/pages/about.js(关于我们页面) const AboutPage = ({ toggleActive }) => { return <div>切换按钮状态:{toggleActive ? '开启' : '关闭'}</div> }
方案2:React Context(适合多组件/多层嵌套需要共享状态的场景)
如果你的项目嵌套层级深,或者有很多不相关的组件都需要用到这个切换状态,用状态提升会出现props透传的冗余问题,直接用React Context即可:
- 第一步:新建context文件定义全局状态
// src/context/ToggleContext.js import React, { createContext, useContext, useState } from 'react' const ToggleContext = createContext() export const ToggleProvider = ({ children }) => { const [toggleActive, setToggleActive] = useState(false) return ( <ToggleContext.Provider value={{ toggleActive, setToggleActive }}> {children} </ToggleContext.Provider> ) } export const useToggle = () => useContext(ToggleContext)
- 第二步:在Gatsby的根包装组件里注入Provider,需要同步修改以下两个文件保证服务端渲染和客户端逻辑一致:
gatsby-browser.js(浏览器端全局生效)gatsby-ssr.js(服务端渲染生效)
// gatsby-browser.js / gatsby-ssr.js import React from 'react' import { ToggleProvider } from './src/context/ToggleContext' export const wrapRootElement = ({ element }) => { return <ToggleProvider>{element}</ToggleProvider> }
- 第三步:Header组件和所有业务页面直接用自定义hook获取状态即可
// header.js里的用法 import { useToggle } from '../context/ToggleContext' const Header = () => { const { toggleActive, setToggleActive } = useToggle() return <button onClick={() => setToggleActive(!toggleActive)}>切换按钮</button> }
// about.js里的用法 import { useToggle } from '../context/ToggleContext' const AboutPage = () => { const { toggleActive } = useToggle() return <div>切换状态:{toggleActive ? '开启' : '关闭'}</div> }
内容的提问来源于stack exchange,提问作者Zinal Patel
相关产品推荐
相关产品推荐

