【发布时间】:2018-08-28 02:43:40
【问题描述】:
我创建了一个 reactJS 应用程序,使用 create-react-app 使用 Flux 作为架构,我希望某些路由无需经过身份验证即可访问,而某些路由仅在经过身份验证后才能访问。使用通量设计模式,我使用 props 将 store 的状态向下传递到每个组件,因此 store 状态可用于所有需要它的子组件。
我研究了文档here(示例也粘贴在下面)以尝试了解如何在我的应用程序中实现上述结果。
我看不出如何调整示例以将状态传递给在受保护路由中调用的组件,而无需使用明确的名称(例如组件的传递方式)进行此操作。我想实现...
- 将组件传递给 PrivateRoute,以便在我的用户通过身份验证时调用它。
- 将父组件中的所有道具传递给 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 未定义。
【问题讨论】:
-
如果你这样做
<PrivateRoute path="/protected" component={Protected} extra="extra prop"/>会怎样?Protected组件不接收this.props.extra吗? -
我知道 this.props.extra 是未定义的。
-
更多信息...如果我尝试只传递一个道具,道具只会包含匹配、位置、历史和 staticContext 事件。
标签: reactjs react-router