我是React和Redux的新手,我试图创建一个私有的嵌套路由。登录时,我被重定向到/ userdashboard,令牌也从服务器返回并存储到本地存储中。 每当http://localhost:3000/userdashboard/post中的Im被加载时,帖子就会被加载。 但是,当我刷新AUTH_ERROR操作时,便会分派该令牌,并且该令牌会从本地存储中删除,并且会被重定向。
我尝试调用相同的操作以将用户加载到嵌套组件上,但是仍然派发了AUTH_ERROR操作
我的App.js
import React, { Fragment, useEffect } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Landing from './components/layout/Landing/Landing';
import Register from './components/auth/Register';
import Login from './components/auth/Login';
import Alert from './components/layout/Alert/Alert';
import UserDasboard from './components/userdashboard/UserDashboard';
import PrivateRoute from './components/routing/PrivateRoute';
//Redux
import { Provider } from 'react-redux';
import store from './store';
import { loadUser } from './actions/auth';
import setAuthToken from './utils/setAuthToken';
import './App.scss';
if (localStorage.token) {
setAuthToken(localStorage.token);
}
const App = () => {
useEffect(() => {
store.dispatch(loadUser());
}, []);
return (
<Provider store={store}>
<Router>
<Fragment>
<Alert />
<Switch>
<PrivateRoute path='/userdashboard' component={UserDasboard} />
<Route exact path='/register' component={Register} />
<Route exact path='/login' component={Login} />
<Route exact path='/' component={Landing} />
</Switch>
</Fragment>
</Router>
</Provider>
);
};
export default App;
// UserDashboard
import React, { Fragment, useEffect, useState } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import PropTypes from 'prop-types';
import Navbar from '../layout/Navbar/Navbar';
import SideBar from '../layout/SideBar/SideBar';
import Posts from '../../components/posts/Posts';
const UserDashboard = props => {
const [showSidebar, setShowSidebar] = useState(true);
const toggleSideBar = () => setShowSidebar(!showSidebar);
return (
<Router>
<Fragment>
<Navbar />
<div className='columns is-mobile'>
<SideBar showSidebar={showSidebar} />
<div className='column'>
<div className='columns is-mobile'>
<div
className='column is-2-desktop is-2-mobile'
onClick={toggleSideBar}
>
<button></button>
</div>
<div className='column is-3-desktop is-3-mobile is-offset-4'>
Dashboard
</div>
</div>
<Switch>
<Route path={props.match.url + '/post'} component={Posts} />
<Route
path={props.match.url + '/new-post'}
render={() => <p>Hello</p>}
/>
</Switch>
</div>
</div>
</Fragment>
</Router>
);
};
UserDashboard.propTypes = {};
export default UserDashboard;
//发布
import React, { Fragment, useEffect } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import PostItem from './PostItem';
import { getPosts } from '../../actions/post';
const Posts = ({ getPosts, post: { posts, loading } }) => {
useEffect(() => {
getPosts();
}, [getPosts]);
return loading ? (
<p>Loading</p>
) : (
<Fragment>
<section className='section'>
<div className='columns'>
{/* Post form*/}
<div className='columns'>
{posts.map(post => (
<PostItem
key={post._id}
post={post}
subs={post.subscribedusers}
/>
))}
</div>
</div>
</section>
</Fragment>
);
};
Posts.propTypes = {
getPosts: PropTypes.func.isRequired,
post: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
post: state.post
});
export default connect(
mapStateToProps,
{ getPosts }
)(Posts);
// PostItem
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import Moment from 'react-moment';
import { connect } from 'react-redux';
import { addSubscriber, removeSubscriber } from '../../actions/post';
const PostItem = ({
addSubscriber,
removeSubscriber,
auth,
post: {
_id,
posttitle,
posttext,
postimage,
user,
subscribedusers,
userposts,
date
},
subs
}) => {
const sub = subs.map(sub => sub);
return (
<div className='column'>
<Link to={`/post/${_id}`}>
<div class='card'>
<div class='card-image'>
<figure class='image is-4by3'>
<img src={postimage} alt='Placeholder image' />
</figure>
</div>
<div class='card-content'>
<div class='media'>
<div class='media-left'>
<figure class='image is-48x48'>
<img
src='#'
alt='Placeholder image'
/>
</figure>
</div>
<div class='media-content'>
<p class='title is-4'>{posttitle}</p>
{/* <p class='subtitle is-6'>@johnsmith</p> */}
</div>
</div>
<div class='content'>
<p>{posttext}</p>
<br />
<time datetime='2016-1-1'>
<Moment format='YYYY/MM/DD'>{date}</Moment>
</time>
</div>
<footer class='card-footer'>
<p class='card-footer-item'>
Subscriptions{' '}
{subscribedusers.length > 0 && (
<span>{subscribedusers.length}</span>
)}
</p>
<p class='card-footer-item'>{userposts.length}</p>
<button className='button' onClick={e => addSubscriber(_id)}>
Subscribe
</button>
<button className='button' onClick={e => removeSubscriber(_id)}>
UnSubscribe
</button>
</footer>
</div>
</div>
</Link>
</div>
);
};
PostItem.propTypes = {
post: PropTypes.object.isRequired,
auth: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
auth: state.auth
});
export default connect(
mapStateToProps,
{ addSubscriber, removeSubscriber }
)(PostItem);
./actions/auth中的// loadUser
export const loadUser = () => async dispatch => {
if (localStorage.token) {
setAuthToken(localStorage.token);
}
try {
const res = await axios.get('userapi/auth');
dispatch({
type: USER_LOADED,
payload: res.data
});
} catch (err) {
dispatch({
type: AUTH_ERROR
});
}
};
// setAuthToken
import axios from 'axios';
const setAuthToken = token => {
if (token) {
axios.defaults.headers.common['x-auth-token'] = token;
} else {
delete axios.defaults.headers.common['x-auth-token'];
}
};
export default setAuthToken;