如何将身份验证状态传递给嵌套组件

时间:2019-09-12 01:10:50

标签: javascript reactjs redux react-redux react-router

我是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;

0 个答案:

没有答案