需要帮助使用 react redux 和 firebase
制作私有路由
问题是:
当我点击登录时,用户正确签名并且状态在 redux 商店中更新,但用户没有被重定向到仪表板,但在单击按钮登录后输入“/dashboard”URL 有效,也尝试去“ /dashboard" 当用户状态 user null 工作时
App.js
import React, { useEffect } from "react";
import { connect, Provider } from "react-redux";
import store from "./store";
import { setUser, clearUser } from "./actions/userActions";
import {
BrowserRouter as Router,
Route,
Switch,
withRouter,
} from "react-router-dom";
import Login from "./components/auth/Login";
import Register from "./components/auth/Register";
import Home from "./components/pages/Home";
import Dashboard from "./components/pages/Dashboard";
import firebase from "./firebase";
import PrivateRoute from "./components/PrivateRoute";
function App({ setUser, clearUser, currentUser, history, isLoading }) {
useEffect(() => {
const unsubscribe = firebase.auth().onAuthStateChanged((user) => {
if (user) {
setUser(user);
} else {
clearUser();
}
});
return () => {
unsubscribe();
clearUser();
};
}, [clearUser, history, setUser]);
return (
<Switch>
<Route path="/" component={Home} exact />
<PrivateRoute
path="/dashboard"
component={Dashboard}
currentUser={currentUser}
isLoading={isLoading}
/>
<Route path="/login" component={Login} />
<Route path="/register" component={Register} />
</Switch>
);
}
const mapStateToProps = (state) => ({
isLoading: state.user.isLoading,
currentUser: state.user.currentUser,
});
const AppWithRouter = withRouter(
connect(mapStateToProps, { setUser, clearUser })(App)
);
const AppWithAuth = () => (
<Provider store={store}>
<Router>
<AppWithRouter />
</Router>
</Provider>
);
export default AppWithAuth;
PrivateRoute.js
import React from "react";
import { Redirect, Route } from "react-router-dom";
const PrivateRoute = ({
component: Component,
currentUser,
isLoading,
...rest
}) => {
return isLoading ? (
<h1>Spinner</h1>
) : (
<Route
{...rest}
render={(props) =>
currentUser ? <Component {...props} /> : <Redirect to="login" />
}
/>
);
};
export default PrivateRoute;
Login.js
import React, { useState } from "react";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
//firebase
import firebase from "../../firebase";
import {
Grid,
Box,
TextField,
CssBaseline,
Avatar,
Container,
Typography,
LinearProgress,
Button,
makeStyles,
} from "@material-ui/core";
const Login = (props) => {
const [form, setForm] = useState({
email: "",
password: "",
});
const [errors, setErrors] = useState([]);
const [loading, setLoading] = useState(false);
const handleChange = (event) =>
setForm({ ...form, [event.target.name]: event.target.value });
const handleSubmit = (e) => {
e.preventDefault();
if (!form.email || !form.password) {
return setErrors(["Fill in all fields"]);
}
setErrors([]);
setLoading(true);
firebase
.auth()
.signInWithEmailAndPassword(form.email, form.password)
.then((signedInUser) => {
setLoading(false);
props.history.push("dashboard");
})
.catch((err) => {
setLoading(false);
setErrors([err.message]);
});
};
const useStyles = makeStyles((theme) => ({
paper: {
marginTop: theme.spacing(8),
display: "flex",
flexDirection: "column",
alignItems: "center",
},
avatar: {
margin: theme.spacing(1),
backgroundColor: theme.palette.secondary.main,
},
form: {
width: "100%", // Fix IE 11 issue.
marginTop: theme.spacing(1),
},
submit: {
margin: theme.spacing(3, 0, 2),
},
}));
const classes = useStyles();
return (
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<Avatar className={classes.avatar}></Avatar>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<form className={classes.form} noValidate onsubmit={handleSubmit}>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="email"
label="Email Address"
name="email"
autoComplete="email"
onChange={handleChange}
/>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
onChange={handleChange}
/>
<Box color="red">
{errors.length > 0 && errors.map((err, i) => <span>{err}</span>)}
</Box>
<Grid justify="center"></Grid>
{loading ? <LinearProgress size={14} /> : ""}
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
onClick={handleSubmit}
>
Sign in
</Button>
<Grid container>
<Grid item>
<Link to="/register" variant="body2">
{"Don't have an account? Sign Up"}
</Link>
</Grid>
</Grid>
</form>
</div>
<Box mt={8}></Box>
</Container>
);
};
const mapStateToProps = (state) => ({
isLoading: state.user.isLoading,
currentUser: state.user.currentUser,
});
export default connect(mapStateToProps)(Login);