React Router v4 Redirect无法重定向

时间:2017-07-13 16:39:51

标签: reactjs meteor react-router-v4

onEnter替换为render我更改了代码以匹配路由器v4规范。关键是要防止/signup页面在登录时显示。我的代码中有哪些错过?

import React from 'react';
import ReactDOM from 'react-dom';
import {Meteor} from 'meteor/meteor';
import {BrowserRouter, Route, Redirect, Switch} from 'react-router-dom';
import browserHistory from 'history';
import {Tracker} from 'meteor/tracker';

import Signup from '../imports/ui/Signup';
import MyLink from '../imports/ui/MyLink';
import NotFound from '../imports/ui/NotFound';
import Login from '../imports/ui/Login';

const history = browserHistory.createBrowserHistory();

const unathenticatedPages = ['/', '/signup'];
const athenticatedPages = ['/mylink'];
const onEnterPublicPage = () => {
  if (Meteor.userId()) {
    return <Redirect to="/mylink/" />;
  }
};

const routes = (
  <BrowserRouter history={history}>
    <Switch>
      <Route exact path="/" component={Login} render={() => onEnterPublicPage} />
      <Route path="/signup" component={Signup} render={() => onEnterPublicPage} />
      <Route path="/login" component={Login} />
      <Route path="/mylink" component={MyLink} />
      <Route path="*" component={NotFound} />
    </Switch>
  </BrowserRouter>
);

Tracker.autorun(() => {
  const isAuthenticated = !!Meteor.userId();    
  const pathname = history.location.pathname;

  const isUnathenticatedPage = unathenticatedPages.includes(pathname);
  const isAthenticatedPage = athenticatedPages.includes(pathname);

  if (isAuthenticated && isUnathenticatedPage) {
    history.push('/mylink');
  } else if (!isAuthenticated && isAthenticatedPage) {
    history.push('/');
  }
});

Meteor.startup(() => {
  ReactDOM.render(routes, document.getElementById('app'));
});

2 个答案:

答案 0 :(得分:1)

使用React Router 4,您不再像这样使用Browserhistory。相反,它包含在BrowserRouter中,就像您看到in the documentation

此外,我不确定这是否能解决问题,但我制作了App组件并将路由放在那里。然后,使用v4,历史记录在props中出现。然后,您可以运行逻辑并执行props.history.push(url)

编辑:以下是我用来实现此功能的代码:

import React from 'react';
import Header from './Header';
import BinsList from './bins/BinsList';
import BinsMain from './bins/BinsMain';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

const App = (props) => {
  return (
    <Router>
      <div>
        <Header />
        <Switch>
          <Route exact path="/" component={BinsList}></Route>
          <Route path="/bins/:binId" component={BinsMain}></Route>
        </Switch>
      </div>
    </Router>
  );
}

export default App;

我的标题就像这样呈现:

import React, { Component } from 'react';
import Accounts from './Accounts';
import { Link, Redirect, withRouter } from 'react-router-dom'


class Header extends Component {
  onBinClick(e){
    e.preventDefault();
    Meteor.call('bins.insert', (err, bin) => {
      const url = `/bins/${bin}`;
      this.props.history.push(url);
    });
  }

  render() {
    return (
      <nav className="nav navbar-default">
        <div className="navbar-header">
          <Link to="/" className="navbar-brand">MarkBin</Link>
        </div>
        <ul className="nav navbar-nav">
          <li>
            <Accounts />
          </li>
          <li>
            <a href="#" onClick={this.onBinClick.bind(this)}>Create Bin</a>
          </li>
        </ul>
      </nav>
    );
  }
}

export default withRouter(Header);

答案 1 :(得分:0)

现在几乎可以使用这些更改:

import React from 'react';
import ReactDOM from 'react-dom';
import {Meteor} from 'meteor/meteor';
import {BrowserRouter, Route, Redirect, Switch} from 'react-router-dom';
import browserHistory from 'history';
import {Tracker} from 'meteor/tracker';

import Signup from '../imports/ui/Signup';
import MyLink from '../imports/ui/MyLink';
import NotFound from '../imports/ui/NotFound';
import Login from '../imports/ui/Login';

const history = browserHistory.createBrowserHistory();

const unathenticatedPages = ['/', '/signup'];
const athenticatedPages = ['/mylink'];
const isLoggedIn = () => {
  return Meteor.userId() !== null;
};

const routes = (
  <BrowserRouter>
    <Switch >
      <Route exact path="/" render={() => (isLoggedIn() ? <Redirect to="/mylink"/> : <Login/>)} />
      <Route path="/signup" render={() => (isLoggedIn() ? <Redirect to="/mylink"/> : <Signup/>)} />
      <Route path="/login" render={() => (isLoggedIn() ? <Redirect to="/mylink"/> : <Login/>)} />
      <Route path="/mylink" render={() => (!isLoggedIn() ? <Login/> : <MyLink history={history}/>)} />
      <Route path="*" component={NotFound} />
    </Switch>
  </BrowserRouter>
);

Tracker.autorun(() => {
  const isAuthenticated = !!Meteor.userId();
  console.log("isAuthenticated: ", isAuthenticated);

  const pathname = history.location.pathname;
  console.log("pathname: ", pathname);

  const isUnathenticatedPage = unathenticatedPages.includes(pathname);
  const isAthenticatedPage = athenticatedPages.includes(pathname);

  if (isLoggedIn() && isUnathenticatedPage) {
    history.replace('/mylink');
  } else if (!isLoggedIn() && isAthenticatedPage) {
    history.replace('/');
  }
});

Meteor.startup(() => {
  ReactDOM.render(routes, document.getElementById('app'));
});

MyLink.js组件:

import React from 'react';
import {Accounts} from 'meteor/accounts-base';
import {withRouter} from 'react-router-dom';

class MyLink extends React.Component {    
  navigate(evt) {
    evt.preventDefault();
    this.props.history.push('/notfound');
  }

  onLogout() {
    Accounts.logout();
  }

  render() {
    return (
      <div>
        <p>MyLink</p>
        <button onClick={this.navigate.bind(this)}>Go to Not Found page</button>
        <br/>
        <button onClick={this.onLogout.bind(this)}>Log out</button>
      </div>
    );
  }
}

export default withRouter(MyLink);