解决方案是将isOpen
个状态提升到公共祖先组件,并将状态和更新器/回调作为props 向下传递到适当的组件.
基本的琐碎例子:
报头
export default function 报头({ isOpen, menuToggle }) {
return (
<header className={["header", isOpen ? "open" : "closed"].join(" ")}>
<button onClick={menuToggle}>Toggle menu</button>
</header>
);
}
英雄
export default function 英雄({ menuToggle }) {
return (
<section className="hero">
<button onClick={menuToggle}>Toggle menu</button>
</section>
);
}
const ParentComponent = () => {
const [isOpen, setIsOpen] = React.useState(false);
const menuToggle = event => {
setIsOpen(open => !open);
};
return (
<>
<报头 isOpen={isOpen} menuToggle={menuToggle} />
<英雄 menuToggle={menuToggle} />
</>
);
};
If there isn't a direct parent-child relationship between these components then you can either pass the props through all intermediate components until you get to both 报头
and 英雄
, or you can implement a React Context to provide the value and avoid the props drilling issue.
示例:
export const MenuContext = React.createContext({
isOpen: false,
menuToggle: () => {},
});
export const useMenuContext = () => React.useContext(MenuContext);
const MenuContextProvider = ({ children }) => {
const [isOpen, setIsOpen] = React.useState(false);
const menuToggle = event => {
setIsOpen(open => !open);
};
return (
<MenuContext.Provider value={{ isOpen, menuToggle }}>
{children}
</MenuContext.Provider>
);
};
export default MenuContextProvider;
将MenuContextProvider
渲染为公共祖先组件,下游使用useMenuContext
来访问上下文值,无论组件在哪里.
App
const App = () => {
...
return (
<MenuContextProvider>
...
... 报头 somewhere down the ReactTree ...
... 英雄 somewhere down the ReactTree ...
...
</MenuContextProvider>
);
};
报头
export default function 报头() {
const { isOpen, menuToggle } = useMenuContext();
return (
<header className={["header", isOpen ? "open" : "closed"].join(" ")}>
<button onClick={menuToggle}>Toggle menu</button>
</header>
);
}
英雄
export default function 英雄() {
const { menuToggle } = useMenuContext();
return (
<section className="hero">
<button onClick={menuToggle}>Toggle menu</button>
</section>
);
}
更多详情请参见: