我查看了以前的所有答案,但没有一个能解决我的问题。我是react的新手,目前正在做一个宠物项目,我正在使用带有typescript、redux和material UI的react。
由于某种原因,尝试从组件内部重定向会更改url,但不会呈现
匹配的组件(即,它默认为我的404页面,尽管实际路径在同一路由器下(。
我的代码如下-
在这个页面上,我试图将用户重定向到项目页面,以防他已经登录-组件DidMount上的history.push here"失败">
登录.tsx页面:
import React from "react";
import { bindActionCreators, Dispatch } from "redux";
import { withRouter } from "react-router-dom";
import { connect } from "react-redux";
import Typography from "@material-ui/core/Typography";
import {
StyledComponentProps,
Theme,
withStyles,
} from "@material-ui/core/styles";
import Avatar from "@material-ui/core/Avatar";
import Button from "@material-ui/core/Button";
import CssBaseline from "@material-ui/core/CssBaseline";
import TextField from "@material-ui/core/TextField";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import Checkbox from "@material-ui/core/Checkbox";
import Link from "@material-ui/core/Link";
import Grid from "@material-ui/core/Grid";
import LockOutlinedIcon from "@material-ui/icons/LockOutlined";
import Container from "@material-ui/core/Container";
import CenteredForm from "../../components/CenteredForm";
import {
isEmailValid,
isPasswordValid,
} from "../../core/validators/authValidators";
import { loginUser } from "./actions";
import { history } from "../history";
interface OwnProps {
email: string;
password: string;
}
interface StyledProps {
classes: StyledComponentProps & any;
}
interface DispatchProps {
loginUser: typeof loginUser;
}
type LoginProps = OwnProps & StyledProps & DispatchProps;
interface LoginState {
email: string;
password: string;
isEnabled: boolean;
}
const initialState: LoginState = {
email: "",
password: "",
isEnabled: false,
};
const styles = (theme: Theme) => ({
avatar: {
margin: theme.spacing(1),
backgroundColor: theme.palette.secondary.main,
},
form: {
width: "100%", // Fix IE 11 issue.
marginTop: theme.spacing(1),
marginBottom: theme.spacing(15),
},
submit: {
margin: theme.spacing(3, 0, 2),
},
});
class Login extends React.Component<LoginProps, LoginState> {
constructor(props: LoginProps, state: LoginState) {
super(props);
this.state = initialState;
this.handleChange = this.handleChange.bind(this);
this.login = this.login.bind(this);
}
componentDidMount() {
if (localStorage.getItem("accessToken")) {
history.push("/projects");
}
}
// https://stackoverflow.com/questions/40676343/typescript-input-onchange-event-target-value
// https://stackoverflow.com/a/52030057/1091286
handleChange = (field: string) => (
event: React.ChangeEvent<HTMLInputElement>
) => {
event.preventDefault();
const newState = { ...this.state, [field]: event.target.value };
newState.isEnabled =
isEmailValid(newState.email) && isPasswordValid(newState.password);
this.setState({
...newState,
});
};
login = (event: React.MouseEvent<HTMLButtonElement>) => {
event.preventDefault();
if (this.state.isEnabled) {
this.props.loginUser({
email: this.state.email,
password: this.state.password,
});
}
};
render() {
const { classes } = this.props;
return (
<Container component="main" maxWidth="xs">
<CssBaseline />
<CenteredForm>
<Avatar className={classes.avatar}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<form className={classes.form} noValidate>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="email"
onChange={this.handleChange("email")}
label="Email Address"
name="email"
autoComplete="email"
autoFocus
/>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
onChange={this.handleChange("password")}
autoComplete="current-password"
/>
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
onClick={this.login}
disabled={!this.state.isEnabled}
className={classes.submit}
>
Sign In
</Button>
<Grid container>
<Grid item xs>
<Link href="/reset-password" variant="body2">
Forgot password?
</Link>
</Grid>
<Grid item>
<Link href="/register" variant="body2">
{"Don't have an account? Sign Up"}
</Link>
</Grid>
</Grid>
</form>
</CenteredForm>
</Container>
);
}
}
function mapStateToProps(state: LoginState) {
return {
email: state.email,
password: state.password,
isEnabled: state.isEnabled,
};
}
function mapDispatchToProps(dispatch: Dispatch) {
return bindActionCreators({ loginUser }, dispatch);
}
const connectedLoginPage = withRouter(
connect<LoginState, any, any, any>(
mapStateToProps,
mapDispatchToProps
// @ts-ignore
)(withStyles(styles)(Login))
);
export { connectedLoginPage as Login };
App.tsx页面:
import React from "react";
import { Component } from "react";
import "./App.css";
import { Router } from "react-router";
import { Switch, Route } from "react-router-dom";
import {
isMobile,
} from "react-device-detect";
import { history } from "../history";
import Header from "../../components/Header";
import Footer from "../../components/Footer";
import Home from "../Home";
import Login from "../Login";
import Register from "../Register";
import ForgotPassword from "../ForgotPassword";
import Projects from "../Projects";
import NotFound from "../NotFound";
class App extends Component {
render() {
if (isMobile) {
return <div> This content is unavailable on mobile</div>;
} else {
return (
<div className="page-container">
<Header />
<div className="content-wrap">
<Router history={history}>
<div>
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/login" component={Login} />
<Route exact path="/register" component={Register} />
<Route
exact
path="/reset-password"
component={ForgotPassword}
/>
<Route exact path="/projects" component={Projects} />
<Route component={NotFound} />
</Switch>
</div>
</Router>
</div>
<Footer />
</div>
);
}
}
}
export default App;
index.tsx页面:
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { ThemeProvider } from "@material-ui/core";
import "./index.css";
import theme from "./theme";
import store from "./store";
import App from "./features/App";
import * as serviceWorker from "./serviceWorker";
ReactDOM.render(
<React.StrictMode>
<ThemeProvider theme={theme}>
<Provider store={store}>
<App />
</Provider>
</ThemeProvider>
</React.StrictMode>,
document.getElementById("root")
);
serviceWorker.unregister();
history.ts类:
import { createBrowserHistory } from "history";
export const history = createBrowserHistory();
有人能告诉我我错过了什么吗?
发布@tachko评论作为答案,最新的历史版本有一个错误,降级到V4.10.1解决了我的问题(使用V5.0.0(https://github.com/ReactTraining/react-router/issues/7415