Каков наилучший способ поделиться некоторыми глобальными значениями и функциями в реакции?
Теперь у меня есть один ContextProvider со всеми ними внутри:
<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)
}}
>
Но как печально в документах :
Поскольку контекст использует ссылочную идентификацию, чтобы определить, когда необходимо выполнить повторную визуализацию, есть некоторые ошибки, которые могут вызвать непреднамеренную визуализацию у потребителей при повторной визуализации родительского объекта поставщика. Например, приведенный ниже код будет повторно отображать всех потребителей каждый раз, когда поставщик выполняет повторную визуализацию, поскольку для значения всегда создается новый объект:
Это плохо:
<Provider value={{something: 'something'}}>
Это нормально:
this.state = {
value: {something: 'something'},
};
<Provider value={this.state.value}>
Я думаю, что в будущем у меня будет до 30 провайдеров контекста, и это не очень дружелюбно: /
Так как я могу передать эти глобальные значения и функции компонентам? Я могу просто
- Создайте отдельный contextProvider для всего.
- Сгруппируйте что-то, что использовалось вместе, например, профиль и его функции,
тема и ее функции (как насчет ссылочной идентичности?)
- Может быть, группа функционирует только потому, что она не меняет себя? какие
о ссылочной идентичности, чем?)
- Другой самый простой способ?
Примеры того, что я использую в провайдере:
// 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})