如何将 prop 传递到 react-router 路由中?
How do I pass a prop into a react-router Route?
我正在尝试通过使用 firebase 构建一个简单的应用程序来深入学习 React router (v4),我正在做的是当用户使用 google 使用 firebase 登录时,他们将被重定向到另一个组件当他们再次进入根路径“/”时,他们将不再看到登录(我通过基于状态重定向来做到这一点)
我有两个问题
我的第一个问题是身份验证成功后,用户将按预期重定向到 /dashboard,但如果我返回或再次键入根路径,登录页面将短暂显示然后重定向。我想是因为我的方法不够快,这是 componentWillMount();
我的第二个问题是我想将一些道具传递给仪表板但我不知道如何,我一直在互联网上寻找和搜索但我不知道如何实现它...
这是我的 login.js,我想将 currentUser 传递给仪表板,并且当用户返回登录路径时,如果他们已登录,我想足够快地重定向他们而不显示登录页面...
state = {
currentUser: null,
successLogin: false
}
googleAuth = () => {
auth.signInWithPopup(provider).then(response => {
const token = response.credential.accessToken;
const currentUser = response.user;
}).catch(error => {
console.log(error.code , 'occured');
})
}
// firebase.auth().signInWithPopup(provider).then(function(result) {
// var token = result.credential.accessToken;
// var user = result.user;
// }).catch(function(error) {
// var errorCode = error.code;
// var errorMessage = error.message;
// var email = error.email;
// var credential = error.credential;
// });
componentDidMount() {
auth.onAuthStateChanged(user => {
if(user) {
console.log('a user was successfuly logged in')
this.setState({
currentUser: user.displayName,
successLogin: true
})
} else {
console.log('eerror')
}
})
}
componentDidUpdate() {
if(this.state.successLogin){
this.props.history.replace("/dashboard");
} else {
console.log('not a successful login');
}
}
componentWillMount() {
if(this.state.successLogin){
<Redirect to="/dashboard"/>
}
}
这是我的仪表板,我正在为用户创建新状态,因为我不知道如何从登录中获取当前用户状态...
state = {
user: null
}
componentDidMount(){
auth.onAuthStateChanged(user => {
this.setState({
user: user.displayName
})
})
}
render(){
const { user } = this.state;
return (
<h1> DashBoard {user}</h1>
)
}
}
这是我的routes.js
<BrowserRouter>
<div>
<Switch>
<Route path='/' exact component={Login} />
<Route path='/register' component={Register} />
<Route path='/dashboard' component={MainDashBoard} />
</Switch>
</div>
</BrowserRouter>
我知道我可以使用 redux 但我还不想跳入 redux....
将 .onAuthStateChanged
代码放在路由文件的 componentDidMount
方法中,而不是仪表板和登录页面。如果您的路由文件是仪表板和登录组件的最低公共祖先,则在那里处理身份验证并将用户作为道具传递给每个路由。基于道具处理重定向,而不是在两个组件中进行身份验证。您不能将 props 直接放入 <Route/>
组件中,因此您必须编写一个 public 或私有 Routes 高阶组件并将 props 作为替换路由组件合并。
我通常只是将它们放在我的路由文件的底部,或者您可以将它们存储在自己的文件中并导入它们。
const renderMergedProps = (component, ...rest) => {
const finalProps = Object.assign({}, ...rest)
return React.createElement(component, finalProps)
}
const PublicRoute = ({ component, ...rest }) => {
return (
<Route
{...rest}
render={routeProps => {
return renderMergedProps(component, routeProps, rest)
}}
/>
)
}
const PrivateRoute = ({ component, authed, ...rest }) => {
return (
<Route
{...rest}
render={routeProps =>
authed === true ? (
renderMergedProps(component, routeProps, rest)
) : (
<Redirect
to={{ pathname: '/login', state: { from: routeProps.location } }}
/>
)}
/>
)
}
现在你可以使用这些高阶组件来代替 <Router/>
组件,但是你的用户属性被合并了(或者你可以使用 authed
布尔属性来显示是否有人登录或者不必传递整个用户对象,在状态中设置一个 authed
布尔值,并在 onAuthStateChanged
注册用户时将其变为真。
<BrowserRouter>
<div>
<Switch>
<PublicRoute
exact
path='/'
component={Login}
authed={this.state.authed} />
<PrivateRoute
path="/dashboard"
component={MainDashBoard}
user={this.state.user}
/>
</Switch>
</div>
</BrowserRouter>
我正在尝试通过使用 firebase 构建一个简单的应用程序来深入学习 React router (v4),我正在做的是当用户使用 google 使用 firebase 登录时,他们将被重定向到另一个组件当他们再次进入根路径“/”时,他们将不再看到登录(我通过基于状态重定向来做到这一点)
我有两个问题
我的第一个问题是身份验证成功后,用户将按预期重定向到 /dashboard,但如果我返回或再次键入根路径,登录页面将短暂显示然后重定向。我想是因为我的方法不够快,这是 componentWillMount();
我的第二个问题是我想将一些道具传递给仪表板但我不知道如何,我一直在互联网上寻找和搜索但我不知道如何实现它...
这是我的 login.js,我想将 currentUser 传递给仪表板,并且当用户返回登录路径时,如果他们已登录,我想足够快地重定向他们而不显示登录页面...
state = {
currentUser: null,
successLogin: false
}
googleAuth = () => {
auth.signInWithPopup(provider).then(response => {
const token = response.credential.accessToken;
const currentUser = response.user;
}).catch(error => {
console.log(error.code , 'occured');
})
}
// firebase.auth().signInWithPopup(provider).then(function(result) {
// var token = result.credential.accessToken;
// var user = result.user;
// }).catch(function(error) {
// var errorCode = error.code;
// var errorMessage = error.message;
// var email = error.email;
// var credential = error.credential;
// });
componentDidMount() {
auth.onAuthStateChanged(user => {
if(user) {
console.log('a user was successfuly logged in')
this.setState({
currentUser: user.displayName,
successLogin: true
})
} else {
console.log('eerror')
}
})
}
componentDidUpdate() {
if(this.state.successLogin){
this.props.history.replace("/dashboard");
} else {
console.log('not a successful login');
}
}
componentWillMount() {
if(this.state.successLogin){
<Redirect to="/dashboard"/>
}
}
这是我的仪表板,我正在为用户创建新状态,因为我不知道如何从登录中获取当前用户状态...
state = {
user: null
}
componentDidMount(){
auth.onAuthStateChanged(user => {
this.setState({
user: user.displayName
})
})
}
render(){
const { user } = this.state;
return (
<h1> DashBoard {user}</h1>
)
}
}
这是我的routes.js
<BrowserRouter>
<div>
<Switch>
<Route path='/' exact component={Login} />
<Route path='/register' component={Register} />
<Route path='/dashboard' component={MainDashBoard} />
</Switch>
</div>
</BrowserRouter>
我知道我可以使用 redux 但我还不想跳入 redux....
将 .onAuthStateChanged
代码放在路由文件的 componentDidMount
方法中,而不是仪表板和登录页面。如果您的路由文件是仪表板和登录组件的最低公共祖先,则在那里处理身份验证并将用户作为道具传递给每个路由。基于道具处理重定向,而不是在两个组件中进行身份验证。您不能将 props 直接放入 <Route/>
组件中,因此您必须编写一个 public 或私有 Routes 高阶组件并将 props 作为替换路由组件合并。
我通常只是将它们放在我的路由文件的底部,或者您可以将它们存储在自己的文件中并导入它们。
const renderMergedProps = (component, ...rest) => {
const finalProps = Object.assign({}, ...rest)
return React.createElement(component, finalProps)
}
const PublicRoute = ({ component, ...rest }) => {
return (
<Route
{...rest}
render={routeProps => {
return renderMergedProps(component, routeProps, rest)
}}
/>
)
}
const PrivateRoute = ({ component, authed, ...rest }) => {
return (
<Route
{...rest}
render={routeProps =>
authed === true ? (
renderMergedProps(component, routeProps, rest)
) : (
<Redirect
to={{ pathname: '/login', state: { from: routeProps.location } }}
/>
)}
/>
)
}
现在你可以使用这些高阶组件来代替 <Router/>
组件,但是你的用户属性被合并了(或者你可以使用 authed
布尔属性来显示是否有人登录或者不必传递整个用户对象,在状态中设置一个 authed
布尔值,并在 onAuthStateChanged
注册用户时将其变为真。
<BrowserRouter>
<div>
<Switch>
<PublicRoute
exact
path='/'
component={Login}
authed={this.state.authed} />
<PrivateRoute
path="/dashboard"
component={MainDashBoard}
user={this.state.user}
/>
</Switch>
</div>
</BrowserRouter>