反应钩子:useState/context;无法读取未定义的属性“头像”/如何更新嵌套对象
Posted
技术标签:
【中文标题】反应钩子:useState/context;无法读取未定义的属性“头像”/如何更新嵌套对象【英文标题】:React hooks: useState/context; Cannot read property 'avatar' of undefined/How to update a nested object 【发布时间】:2020-09-30 00:49:26 【问题描述】:我已经从上下文文件中传递了一个状态变量和函数:
用户上下文:
import React, useState from 'react';
const UserContext = React.createContext();
function UserProvider( children )
var [userImages, setUserImages] = useState(
avatar: '/static/uploads/profile-avatars/placeholder.jpg'
);
return (
<UserContext.Provider
value=
userImages,
setUserImages
>
children
</UserContext.Provider>
);
export default UserContext;
export UserProvider ;
此时UserImages
只是一个带有一个属性的对象,即avatar
这是我的应用程序正在被 Provider 包装(请忽略 redux 的实现,我只是想试试 Context)
import React from 'react';
import Provider from 'react-redux';
import UserProvider from './UserContext';
import App from 'next/app';
import withRedux from 'next-redux-wrapper';
import PersistGate from 'redux-persist/integration/react';
import reduxStore from '../store/index';
import withReactRouter from '../with-react-router/with-react-router';
class MyApp extends App
static async getInitialProps( Component, ctx )
const pageProps = Component.getInitialProps
? await Component.getInitialProps(ctx)
: ;
return pageProps ;
render()
const Component, pageProps, store = this.props;
return (
<UserProvider>
<Provider store=store>
<PersistGate persistor=store.__PERSISTOR loading=null>
<Component ...pageProps />
</PersistGate>
</Provider>
</UserProvider>
);
我正在尝试使用 post 之后的 setState 函数更新一些上下文
但是我仍然收到TypeError: Cannot read property 'avatar' of undefined
这是状态对象的形状:
userData:
setUserImages: ƒ ()
userImages:
avatar: "/static/uploads/profile-avatars/placeholder.jpg"
或
userData :
setUserImages : SetUserImages function,
userImages :
avatar : "/static/uploads/profile-avatars/placeholder.jpg"
我的组件:
function ImageUploader( userData )
var avatar = userData.userImages;
var setUserAvatar = userData.setUserImages;
function avatarUpdater(avatarPath)
setUserAvatar( userData: ...userData.userImages.avatar, avatarPath );
有人知道为什么会这样吗?
【问题讨论】:
您可能需要先确认userData
和userData.userImages
,然后才能从中获取avatar
。 userData
来自哪里?这个问题与 react-context 有什么关系?
@TonyNguyen 你是对的,也许我应该更新我的问题,我添加了一些上下文......
你在哪里使用ImageUploader
?
【参考方案1】:
UserProvider
是你app的根,所以你可以直接在ImageUploader
中获取userImages, setUserImages
function ImageUploader()
const userImages, setUserImages = useContext(UserContext)
const avatar = userImages;
function avatarUpdater(avatarPath)
setUserImages( avatar: avatarPath );
【讨论】:
【参考方案2】:通常最好的做法是不要从您的上下文中公开setState
。您想将其包装在一个显式方法中以更新状态,然后将该方法添加到您的 Provider 中。比如:
const userContext =
avatar: userImages,
updateAvatarUrl: (url) =>
setUserImages(prevState => (...prevState, avatar: url))
return <UserContext.Provider value=userContext>children</UserContext.Provider>
尝试为你的 UserContext 添加一个钩子,你可以在你的组件中使用它。
在UserContext
添加
export const useUserContext = () => useContext(UserContext)
然后在你的组件内部:
import useUserContext from '<UserContext import>'
...
function avatarUpdater(avatarPath)
userCtx.updateAvatarUrl(avatarPath)
我认为 Context 结构最简洁。允许更精确地控制上下文状态。
【讨论】:
以上是关于反应钩子:useState/context;无法读取未定义的属性“头像”/如何更新嵌套对象的主要内容,如果未能解决你的问题,请参考以下文章
反应:无法使用 useContext 钩子在 app.js 中设置上下文状态