无法合并...函数返回的状态和结果。
我试图将类组件更改为功能组件。
所以我更新了react并使用了钩子。
首先,我想更改类的状态,将setState更改为钩子的状态。
但是钩子的setState替换对象不能像类的setState那样合并。
下面是原始代码
import React from 'react'
import produce from 'immer'
import {
getUserFromCookie,
login,
logout,
profile,
updateProfile
} from '../api'
const userInfo = getUserFromCookie()
const UserContext = React.createContext({
...userInfo
})
export const withUserContext = WrappedComponent => {
return class ProviderComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
...userInfo,
consentNeeded: false,
updateConsent: async ({ pi, news, seen }) => {
await updateProfile({ pi, news, seen })
this.setState({
consentNeeded: false
})
},
profile: async () => {
const userProfile = await profile()
if (userProfile.seen_consent_modal === false) {
this.setState({
consentNeeded: true
})
}
},
login: async ({ userId, password }) => {
const user = await login({ userId, password })
this.setState(
produce(draft => {
return user
})
)
},
logout: async () => {
await logout()
}
}
}
render() {
return (
<UserContext.Provider value={this.state}>
<WrappedComponent {...this.props} />
</UserContext.Provider>
)
}
}
}
export default UserContext
这是我工作的功能组件。
import React, { useState } from 'react'
import produce from 'immer'
import {
getUserFromCookie,
login,
logout,
profile,
updateProfile
} from '../api'
const userInfo = getUserFromCookie()
const UserContext = React.createContext({
...userInfo
})
export const withUserContext = WrappedComponent => {
return function provideComponent() {
const [state, setState] = useState({
...userInfo,
consentNeeded: false,
updateConsent: async ({ pi, news, seen }) => {
console.error('updateConsent!!')
await updateProfile({ pi, news, seen })
setState({
consentNeeded: false
})
},
profile: async () => {
console.error('profile!!')
const userProfile = await profile()
if (userProfile.seen_consent_modal === false) {
setState({
consentNeeded: true
})
}
},
login: async ({ userId, password }) => {
const user = await login({ userId, password })
setState(
produce(() => user)
)
},
logout: async () => {
await logout()
}
})
return (
<UserContext.Provider value={state}>
<WrappedComponent {...props} />
</UserContext.Provider>
)
}
}
export default UserContext
下划线警告。我认为语法不正确
答案 0 :(得分:0)
我意识到了问题所在。我做了一个codesandbox,一切正常(除了您未提供的功能)。
HOC
应该用于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>
)
}
HOC
。 React Hooks引入了useContext
。
现在,您唯一需要渲染Context.Provider
并像const {...contextValue} = useContext(MyContext)
这样使用它。
例如
const { updateConsent, profile, login, logout, ...otherStuff } = useContex(UserContext)
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>
)