问题::当我使用history.push()
时,可以看到浏览器更改了url,但是它没有使我的组件在路径上侦听。仅在刷新页面时才会呈现。
App.js
文件:
import React from "react";
import { BrowserRouter as Router, Route } from "react-router-dom";
import { Provider } from "react-redux";
import PropTypes from "prop-types";
//Components
import LoginForm from "../LoginForm/LoginForm";
import PrivateRoute from "../PrivateRoute/PrivateRoute";
import ServerList from "../ServerList/ServerList";
const App = ({ store }) => {
const isLoggedIn = localStorage.getItem("userToken");
return (
<Router>
<Provider store={store}>
<div className="App">
{isLoggedIn !== true && (
<Route exact path="/login" component={LoginForm} />
)}
<PrivateRoute
isLoggedIn={!!isLoggedIn}
path="/"
component={ServerList}
/>
</div>
</Provider>
</Router>
);
};
App.propTypes = {
store: PropTypes.object.isRequired
};
export default App;
我在LoginForm
内向API发出请求,并在完成程序后使用.then()
重定向我的用户:
.then(() => {
props.history.push("/");
})
会发生什么:浏览器将网址从/login
更改为/
,但是除非渲染页面重新加载,否则不会呈现在/
路由上侦听的组件。
在我的/
组件中,我使用useEffect()
钩子向API发出另一个请求,该请求将提取数据并将其打印在return()
内。如果我在console.log
内useEffect()
发生两次,则假定是第一个,当我使用useState()
钩子将API中的数据存储在组件状态内时。
编辑:根据要求添加PrivateRoute
组件:
import React from "react";
import { Route, Redirect } from "react-router-dom";
const PrivateRoute = ({ component: Component, isLoggedIn, ...rest }) => {
return (
<Route
{...rest}
render={props =>
isLoggedIn === true ? (
<Component {...props} />
) : (
<Redirect to={{ pathname: "/login" }} />
)
}
/>
);
};
export default PrivateRoute;
我已经尝试过的方法:
1)用default export
包装我的withRouter()
:
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(LoginForm));
2)创建自定义history
并将其作为prop
传递给Router
。
react-router-dom
的版本为^5.0.1
。 react-router
相同,5.0.1
答案 0 :(得分:0)
您的代码有两个错误。
您没有使用<switch>
组件来包装路由。因此,每个路由都会处理所有路由,并且每个<route>
的所有组件都会被渲染。
您正在使用本地存储在组件之间交换信息。但是,本地存储中的更改无法做出反应,因此不会触发组件重新渲染。要解决此问题,您应该在App
组件中使用局部状态(通过将其转换为类或使用钩子)。
所以纠正后的代码看起来像
const App = ({ store }) => {
const [userToken, setUserToken] = useState(localStorage.getItem("userToken")); // You can read user token from local store. So on after token is received, user is not asked for login
return (
<Router>
<Provider store={store}>
<div className="App">
<Switch>
{!!userToken !== true && (
<Route exact path="/login"
render={props => <LoginForm {...props} setUserToken={setUserToken} />}
/>
)}
<PrivateRoute
isLoggedIn={!!userToken}
path="/"
component={ServerList}
/>
</Switch>
</div>
</Provider>
</Router>
);
};
并且LoginForm
应该使用setUserToken
来更改App
组件中的用户令牌。它还可以将用户令牌存储在本地存储中,以便不要求页面刷新用户登录,而是使用存储的令牌。
此外,请确保不要在<Switch>
和</Switch>
之间放置任何内容。否则路由将无法工作。