Редактировать:
Я понял, в чем проблема.Я сделал коды и коробку , где все работает (кроме функций, которые вы не предоставили).
1.HOC
s следует использовать для Contex.Consumer
Не Context.Provider
В вашем коде вы делаете HOC
для Context.Provider
, но правильный путь должен быть для Contex.Consumer
.
Для работы с контекстом вам понадобится
<Contex.Provider>
...
<AnyThingYouWant>
<Context.Consumer>
</Context.Consumer>
</AnyThingYouWant>
</Contex.Provider>
Если вы хотите HOC
для Contex.Provider
, вам нужно всего лишь использовать children
и обернуть его вокруг ваших компонентов
например
const UserContext = React.createContext('my context')
const UserProvider = (props) => {
const value = useState('someState')
return (
<UserContext.Provider value={value}>
{children}
</UserContext.Provider>
)
}
2.Если вы используете функциональные компоненты, вам больше не нужно HOC
.
Введены React Hooks useContext
.
Теперь единственное, что вам нужно отрендеритьContext.Provider
и используйте его вот так const {...contextValue} = useContext(MyContext)
.
например
const { updateConsent, profile, login, logout, ...otherStuff } = useContex(UserContext)
3. Внутри Context.Consumer
вам нужно передать функцию, которая отображает WrappedComponent
При создании HOC
для Context.Consumer
необходимо иметь функцию, которая визуализирует WrappedComponent
и получает props
от потребителя.
Например,
const withUserContext = WrappedComponent => {
return function UserContextHoc(props) {
return (
<UserContext.Consumer>
// function that render the `WrappedComponent`
{consumerProps => <WrappedComponent {...props} {...consumerProps} />}
</UserContext.Consumer>
);
};
};
Если вы делаете что-то подобное, это неправильно
<UserContext.Consumer>
// THIS IS WRONG AND WILL THROW AN ERROR
<WrappedComponent {...props} />
</UserContext.Consumer>
Если вы посмотрите на codesandbox , вы увидите, что оно не дает ошибок, а также во console
внутри MyComponent
, он показывает все, что из UserContext
.
Надеюсь, теперь все стало понятнее.
Старый:
Ваши функции должны быть внеuseState
начальное значение для возможности вызова setState
.
// state has multiple key value
const [state, setState] = useState({
...userInfo,
consentNeeded: false,
})
const updateConsent = async ({ pi, news, seen }) => {
await updateProfile({ pi, news, seen })
setState({
consentNeeded: false
})
}
const profile = async () => {
const userProfile = await profile()
if (userProfile.seen_consent_modal === false) {
// setState(prevState => {
// return {...prevState, {consentNeeded: true}};
// });
setState({
consentNeeded: true
})
}
}
const login = async ({ userId, password }) => {
const user = await login({ userId, password })
// code below change it as produce's result.
// not merging of exist states
// setState(
// produce(() => {
// return user
// })
// )
// what I've tried.. but warning underline..
setState(prevState => {...prevState, produce(() => user)})
}
const logout = async () => {
await logout()
}
return (
<UserContext.Provider value={{
...state,
updateConsent,
profile,
login,
logout,
}>
<WrappedComponent {...props} />
</UserContext.Provider>
)