Background
I'm working on a sidebar component that can be opened from many buttons in the UI. I want to 1) only render it once, 2) grant access to update its isVisible
state to these buttons without drilling props down through a common ancestor.
Expectations vs Reality
I'd expect that I could create a context with its own api method to update an internal state. In my code sample I'm attempting to do this with an IIFE.
Questions
export const SidebarContext = createContext((() => {
const [isVisible, setIsVisible] = useState(false)
return {
isVisible,
toggleVisibility: () => setIsVisible(!isVisible)
}
})())
createContext()
receives the default value. So you're defining a function which is invoked immediately and the result of it will be used as default value for the context. That's where the useState
breaks this rule :
Call Hooks from React function components.
In order to accomplish what you want you can do this:
import React, { createContext, useContext, useState } from "react";
const SidebarContext = createContext();
function Provider({ children }) {
let [isVisible, setIsVisible] = useState(false);
let toggle = useCallback(() => setIsVisible(s => !s), [setIsVisible])
// Pass the `state` and `functions` to the context value
return (
<SidebarContext.Provider value={{ isVisible, toggle }}>
{children}
</SidebarContext.Provider>
);
}
function YourButton() {
let { isVisible, toggle } = useContext(SidebarContext);
return (
<div>
<div>Sidebar is {isVisible : 'open': 'close'}</div>
<button onClick={toggle}>
Toggle
</button>
</div>
);
}
function App() {
return (
<Provider>
<YourButton />
</Provider>
);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.