【问题标题】:Auth Protected Routes React Router V4 - Passing PropsAuth Protected Routes React Router V4 - 传递道具
【发布时间】:2018-08-28 02:43:40
【问题描述】:

我创建了一个 reactJS 应用程序,使用 create-react-app 使用 Flux 作为架构,我希望某些路由无需经过身份验证即可访问,而某些路由仅在经过身份验证后才能访问。使用通量设计模式,我使用 props 将 store 的状态向下传递到每个组件,因此 store 状态可用于所有需要它的子组件。

我研究了文档here(示例也粘贴在下面)以尝试了解如何在我的应用程序中实现上述结果。

我看不出如何调整示例以将状态传递给在受保护路由中调用的组件,而无需使用明确的名称(例如组件的传递方式)进行此操作。我想实现...

  1. 将组件传递给 PrivateRoute,以便在我的用户通过身份验证时调用它。
  2. 将父组件中的所有道具传递给 PrivateRoute 调用的组件(这是为了让我可以通过道具继续级联存储状态,并在用户登录时检查存储状态)。李>

我想我在这里可能误解了一些基本的东西。谁能给点建议?

  import React from "react";
  import {
  BrowserRouter as Router,
  Route,
  Link,
  Redirect,
  withRouter
} from "react-router-dom";

////////////////////////////////////////////////////////////
// 1. Click the public page
// 2. Click the protected page
// 3. Log in
// 4. Click the back button, note the URL each time

const AuthExample = () => (
  <Router>
    <div>
      <AuthButton />
      <ul>
        <li>
          <Link to="/public">Public Page</Link>
        </li>
        <li>
          <Link to="/protected">Protected Page</Link>
        </li>
      </ul>
      <Route path="/public" component={Public} />
      <Route path="/login" component={Login} />
      <PrivateRoute path="/protected" component={Protected} />
    </div>
  </Router>
);

const fakeAuth = {
  isAuthenticated: false,
  authenticate(cb) {
    this.isAuthenticated = true;
    setTimeout(cb, 100); // fake async
  },
  signout(cb) {
    this.isAuthenticated = false;
    setTimeout(cb, 100);
  }
};

const AuthButton = withRouter(
  ({ history }) =>
    fakeAuth.isAuthenticated ? (
      <p>
        Welcome!{" "}
        <button
          onClick={() => {
            fakeAuth.signout(() => history.push("/"));
          }}
        >
          Sign out
        </button>
      </p>
    ) : (
      <p>You are not logged in.</p>
    )
);

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route
    {...rest}
    render={props =>
      fakeAuth.isAuthenticated ? (
        <Component {...props} />
      ) : (
        <Redirect
          to={{
            pathname: "/login",
            state: { from: props.location }
          }}
        />
      )
    }
  />
);

const Public = () => <h3>Public</h3>;
const Protected = () => <h3>Protected</h3>;

class Login extends React.Component {
  state = {
    redirectToReferrer: false
  };

  login = () => {
    fakeAuth.authenticate(() => {
      this.setState({ redirectToReferrer: true });
    });
  };

  render() {
    const { from } = this.props.location.state || { from: { pathname: "/" } };
    const { redirectToReferrer } = this.state;

    if (redirectToReferrer) {
      return <Redirect to={from} />;
    }

    return (
      <div>
        <p>You must log in to view the page at {from.pathname}</p>
        <button onClick={this.login}>Log in</button>
      </div>
    );
  }
}

export default AuthExample;

这是我实际代码中的一部分...

class Page extends React.Component{
  // constructor(props) {
  //   super(props);
  //   }

  render(){
    return(
    <Router>
      <div>
        <Route exact path="/" render={()=><HomePage {...this.props}/>}/>
        <Route path="/login" render={()=><LoginPage {...this.props}/>}/>
        <PrivateRoute exact path="/protected" component={Main} extra="Boo!"/>
      </div>
    </Router>);
  }
}

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route
    {...rest}
    render={(props) =>
      (console.log(this.props.extra) || 1) ? (
        <Component {...props} />
      ) : (
        <Redirect
          to={{
            pathname: "/login",
            state: { from: props.location }
          }}
        />
      )
    }
  />
);

This.props.extra 未定义。

【问题讨论】:

  • 如果你这样做 &lt;PrivateRoute path="/protected" component={Protected} extra="extra prop"/&gt; 会怎样? Protected 组件不接收this.props.extra 吗?
  • 我知道 this.props.extra 是未定义的。
  • 更多信息...如果我尝试只传递一个道具,道具只会包含匹配、位置、历史和 staticContext 事件。

标签: reactjs react-router


【解决方案1】:

如果您正在寻找将额外道具传递给PrivateRoute 的方法,您可以这样做:

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route
    {...rest}
    render={ (props) =>
      ( console.log(props.extra) || 1) ? (
        <Component {...props} {...rest} />
      ) : (
        <Redirect
          to={{
            pathname: "/login",
            state: { from: props.location }
          }}
        />
      )
    }
  />
);

然后

<PrivateRoute exact path="/protected" component={Main} extra="Boo!"/>

Main 现在应该收到extra 属性(连同pathexact)。

【讨论】:

  • 谢谢。我仍然不明白为什么 props.extra 没有在 console.log 语句中定义。你知道为什么会这样吗?
  • 看来render 只传递了某些道具而忽略了其余的。但是如果你这样做 console.log(rest.extra) 它应该返回值。
  • 感谢百万伴侣.. 为我节省了很多时间
猜你喜欢
  • 2020-07-22
  • 2018-11-20
  • 1970-01-01
  • 2018-02-28
  • 2015-07-18
  • 1970-01-01
  • 2018-07-03
  • 2018-06-17
  • 2018-01-17
相关资源
最近更新 更多