我已经实现了我的应用程序的身份验证部分(使用MERN堆栈构建)。登录操作将验证登录数据,然后加载用户数据,然后将路由推送到/dashboard
。在仪表板页面上,我有一个简单的Welcome to the dashboard, {email}!
,但是我收到一条错误消息,告诉它它不能返回null数据。我在导航栏中也有用户的名字和姓氏以及他们的电子邮件,这也产生了返回空数据的错误。我有一个useEffect可以将用户数据加载到App.js
中,但是我仍然收到null错误。
是否可以在渲染之前加载数据?
Index.js
ReactDOM.render(
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
</PersistGate>
</Provider>,
document.getElementById('root')
);
App.js
const App = () => {
const [loading, setLoading] = useState(true);
const dispatch = useDispatch();
useEffect(() => {
// check for token in LS
if (localStorage.token) {
setAuthToken(localStorage.token);
}
dispatch(attemptGetUser())
.then(() => setLoading(false))
.catch(() => setLoading(false));
// Logout user from all tabs if they logout in another tab
window.addEventListener('storage', () => {
if (!localStorage.token) dispatch({ type: LOGOUT });
});
// eslint-disable-next-line
}, []);
return loading ? (
<Loading cover="page" />
) : (
<div className="App">
<Switch>
<Route path="/" component={Views} />
</Switch>
</div>
);
};
redux / thunks / Auth.js
export const attemptLogin = (formData) => async (dispatch) => {
await postLogin(formData)
.then((res) => {
dispatch(login(res.data));
dispatch(push('/dashboard'));
})
.then(() => {
dispatch(attemptGetUser());
})
.catch((error) => {
const errors = error.response.data.message;
dispatch(setAlert('Uh-oh!', errors, 'error'));
});
};
redux / thunks / User.js
export const attemptGetUser = () => async (dispatch) => {
await getUser()
.then((res) => {
dispatch(setUser(res.data));
})
.catch((error) => {
const errors = error.response.data.message;
console.log(errors);
dispatch(setAlert('Uh-oh!', errors, 'danger'));
});
};
视图/应用程序视图/仪表板
const Dashboard = () => {
const { email } = useSelector((state) => state.user.user);
return (
<div>
Welcome to the dashboard,
<strong>{email}</strong>!
</div>
);
};
export default Dashboard;
components / layout-components / NavProfile.js
export const NavProfile = () => {
const { firstName, lastName, email } = useSelector(
(state) => state.user.user
);
const dispatch = useDispatch();
const onLogout = () => {
dispatch(attemptLogout());
};
const profileImg = '/img/avatars/thumb-1.jpg';
const profileMenu = (
<div className="nav-profile nav-dropdown">
<div className="nav-profile-header">
<div className="d-flex">
<Avatar size={45} src={profileImg} />
<div className="pl-3">
<h4 className="mb-0">{firstName} {lastName}</h4>
<span className="text-muted">{email}</span>
</div>
</div>
</div>
<div className="nav-profile-body">
<Menu>
{menuItem.map((el, i) => {
return (
<Menu.Item key={i}>
<a href={el.path}>
<Icon className="mr-3" type={el.icon} />
<span className="font-weight-normal">{el.title}</span>
</a>
</Menu.Item>
);
})}
<Menu.Item key={menuItem.legth + 1} onClick={onLogout}>
<span>
<LogoutOutlined className="mr-3" />
<span className="font-weight-normal">Logout</span>
</span>
</Menu.Item>
</Menu>
</div>
</div>
);
return (
<Dropdown placement="bottomRight" overlay={profileMenu} trigger={['click']}>
<Menu className="d-flex align-item-center" mode="horizontal">
<Menu.Item>
<Avatar src={profileImg} />
</Menu.Item>
</Menu>
</Dropdown>
);
};
export default NavProfile;
答案 0 :(得分:1)
所以错误告诉您在redux状态下state.user.user
是未定义的,这就是为什么您无法解构firstName
,lastName
,email
值的原因。
如果您商店中的state.user.user
至少是一个已定义的空对象({}
),则应该解决对空错误的访问。
const userReducer = (state = { user: {} }, action) => {
...
}
这仍然可能使UI呈现为“未定义”,因此在组件代码中,您需要提供默认值,即
const { firstName = '', lastName = '', email = '' } = useSelector(
(state) => state.user.user
);
另一种方法是在用户化简器切片中具有完全限定的初始状态。
const initialState = {
user: {
firstName: '',
lastName: '',
email: '',
},
};
const userReducer = (state = initialState, action) => {
...
}
答案 1 :(得分:0)
似乎您可以通过更改Redux存储的初始状态来解决此问题。
以您的仪表板组件为例:
const Dashboard = () => {
const { email } = useSelector((state) => state.user.user);
return (
<div>
Welcome to the dashboard,
<strong>{email}</strong>!
</div>
);
};
它期望Redux存储中的用户状态片中存在一个带有电子邮件字符串的用户对象。为noted in their documentation
您可以更新您的createStore
调用以包括Redux存储的初始值,例如createStore({'user': {'user': {'email': ''}}});