用打字稿反应-history.push更改URL,但呈现404页而不是正确的页面

时间:2020-08-31 21:17:08

标签: reactjs typescript react-redux material-ui react-router-dom

我一直在寻找所有以前的答案,但没有一个能够解决我的问题。 我是刚接触React的人,目前正在做一个宠物项目,正在将React与Typescript,redux和Material UI结合使用。

出于某种原因,尝试从组件内部进行重定向会更改url,但不会呈现匹配的组件(即,尽管实际路径位于同一路由器下,但它默认为我的404页面)。

我的代码如下-
在此页面上,我试图将用户重定向到项目页面,以防他已经登录-在componentDidMount上的history.push在此处“失败”。
Login.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();

有人可以告诉我我错过了什么吗?

1 个答案:

答案 0 :(得分:0)

发布@tachko注释作为答案,最新历史记录版本存在错误,降级到V4.10.1解决了我的问题(使用V5.0.0)https://github.com/ReactTraining/react-router/issues/7415