What is the best way to share some global values and functions in react?
Now i have one ContextProvider with all of them inside:
<AllContext.Provider
value={{
setProfile, // second function that changes profile object using useState to false or updated value
profileReload, // function that triggers fetch profile object from server
deviceTheme, // object
setDeviceTheme, // second function that changes theme object using useState to false or updated value
clickEvent, // click event
usePopup, // second function of useState that trigers some popup
popup, // Just pass this to usePopup component
windowSize, // manyUpdates on resize (like 30 a sec, but maybe can debounce)
windowScroll // manyUpdates on resize (like 30 a sec, but maybe can debounce)
}}
>
But like sad in docs: Because context uses reference identity to determine when to re-render, there are some gotchas that could trigger unintentional renders in consumers when a provider’s parent re-renders. For example, the code below will re-render all consumers every time the Provider re-renders because a new object is always created for value:
This is bad:
<Provider value={{something: 'something'}}>
This is ok:
this.state = {
value: {something: 'something'},
};
<Provider value={this.state.value}>
I imagine that in future i will have maybe up to 30 context providers and it's not very friendly :/
So how can i pass this global values and functions to components? I can just
- Create separate contextProvider for everything.
- Group something that used together like profile and it's functions, theme and it's functions (what about reference identity than?)
- Maybe group only functions because thay dont change itself? what about reference identity than?)
- Other simpliest way?
Examples of what i use in Provider:
// Resize
const [windowSize, windowSizeSet] = useState({
innerWidth: window.innerWidth,
innerHeight: window.innerHeight
})
// profileReload
const profileReload = async () => {
let profileData = await fetch('/profile')
profileData = await profileData.json()
if (profileData.error)
return usePopup({ type: 'error', message: profileData.error })
if (localStorage.getItem('deviceTheme')) {
setDeviceTheme(JSON.parse(localStorage.getItem('deviceTheme')))
} else if (profileData.theme) {
setDeviceTheme(JSON.parse(JSON.stringify(profileData.theme)))
} else {
setDeviceTheme(settings.defaultTheme)
}
setProfile(profileData)
}
// Click event for menu close if clicked outside somewhere and other
const [clickEvent, setClickEvent] = useState(false)
const handleClick = event => {
setClickEvent(event)
}
// Or in some component user can change theme just like that
setDeviceTheme({color: red})