玩弄反作用力
创建了一个登录页面,使用MUI、Formik和YUP将邮箱和密码作为输入字段 但是,每当我try 在一个字符之后输入任何文本时,输入都会失go 焦点.其他一切都像预期的那样运行.
如果我将这些代码移到App.js中,则没有问题,但将其移回login.jsx似乎根本不起作用.
以下是我的代码
App.js
import {
Navigate,
RouterProvider,
createBrowserRouter,
} from "react-router-dom";
import { ColorModeContext, useMode } from "./theme";
import Login from "./pages/login/Login";
import { useContext, useState } from "react";
import { AuthContext } from "./context/AuthContext";
import { Box, CssBaseline, ThemeProvider } from "@mui/material";
import Home from "./pages/home/Home";
import ErrorPage from "./pages/error/Error";
import SidebarComponent from "./components/sidebar/Sidebar";
import Register from "./pages/register/Register";
function App() {
const currentUser = useContext(AuthContext);
const [theme, colorMode] = useMode();
const Layout = () => {
<Box
sx={{
display: "flex",
height: "100%",
minHeight: "400px",
}}
>
<SidebarComponent />
<main>rtest</main>
</Box>;
};
const ProtectedRoute = ({ children }) => {
if (!currentUser.user) {
return <Navigate to="/login" />;
}
return children;
};
const router = createBrowserRouter([
{
path: "/",
element: (
<ProtectedRoute>
<Layout />
</ProtectedRoute>
),
children: [
{
path: "/",
element: <Home />,
},
],
errorElement: <ErrorPage />,
},
{
path: "/login",
element: <Login />,
},
{
path: "/login",
element: <Register />,
},
]);
return (
<ColorModeContext.Provider value={colorMode}>
<ThemeProvider theme={theme}>
<CssBaseline />
<div className="App">
<RouterProvider router={router} />
</div>
</ThemeProvider>
</ColorModeContext.Provider>
);
}
export default App;
登录.jsx
import Logo from "../../assets/backticklogo.svg";
import { Link, useNavigate } from "react-router-dom";
import { useContext, useEffect, useState } from "react";
import { AuthContext } from "../../context/AuthContext";
import apiClient from "../../services/api";
import { Box, Button, Stack, TextField, Typography } from "@mui/material";
import styled from "@emotion/styled";
import { useFormik } from "formik";
import * as yup from "yup";
const validationSchema = yup.object({
email: yup
.string("Enter your email")
.email("Enter a valid email")
.required("Email is required"),
password: yup
.string("Enter your password")
.min(8, "Password should be of minimum 8 characters length")
.required("Password is required"),
});
const Login = () => {
const localplainTextToken = localStorage.getItem("plainTextToken") || null;
const [isAuth, setIsAuth] = useState(localStorage.getItem("isAuth") || null);
const [plainTextToken, setplainTextToken] = useState(localplainTextToken);
const remember = true;
const navigate = useNavigate();
const { user, dispatch } = useContext(AuthContext);
useEffect(() => {
isAuth && navigate("/");
}, [isAuth]);
const handleUpdateUser = (userInfo) => {
console.log(userInfo);
dispatch({ type: "LOGIN", payload: userInfo });
localStorage.setItem("user", JSON.stringify(userInfo));
localStorage.setItem("isAuth", true);
setIsAuth(true);
};
const formik = useFormik({
initialValues: {
email: "",
password: "",
},
validationSchema: validationSchema,
onSubmit: async (values) => {
// alert(JSON.stringify(values, null, 2));
try {
await apiClient
.post("login", {
email: values.email,
password: values.password,
})
.then((res) => {
console.log(res);
localStorage.setItem("plainTextToken", res.data.plainTextToken);
setplainTextToken(res.data.plainTextToken);
return res.data;
})
.then(async (data) => {
try {
let user = await apiClient.get(`user/${data.user_id}`, {
headers: {
Authorization: `Bearer ${data.plainTextToken}`,
Accept: "application/json",
},
});
console.log(user);
handleUpdateUser(user.data);
// navigate("/");
} catch (error) {}
});
} catch (error) {
console.log(error);
}
},
});
/***********Styled component */
const LoginContainer = styled(Box)(({ theme }) => ({
display: "flex",
flex: "1 1 auto",
height: "100%",
width: "100%",
[theme.breakpoints.up("xs")]: {
flexDirection: "column-reverse",
},
[theme.breakpoints.up("md")]: {
flexDirection: "row",
},
}));
const RightBox = styled(Box)(({ theme }) => ({
backgroundColor: "rgb(14, 8, 39)",
display: "flex",
flexDirection: "column",
maxWidth: "100%",
[theme.breakpoints.up("xs")]: {
flex: "1 1 auto",
padding: "32px",
},
[theme.breakpoints.up("md")]: {
flex: "0 0 auto",
justifyContent: "center",
padding: "64px",
width: "600px",
},
}));
const LeftBox = styled(Box)(({ theme }) => ({
display: "flex",
alignItems: "center",
backgroundColor: "rgb(28, 37, 54)",
backgroundImage: "url(/assets/gradient-bg.svg)",
backgroundPosition: "center top",
backgroundRepeat: "no-repeat",
color: "rgb(255, 255, 255)",
justifyContent: "center",
[theme.breakpoints.up("xs")]: {
flex: "0 0 auto",
padding: "32px",
},
[theme.breakpoints.up("md")]: {
flex: "1 1 auto",
padding: "64px",
},
}));
return (
<LoginContainer>
<LeftBox>
<Box sx={{ maxWidth: "900px" }}>
<Typography variant="h4"> Welcome to Backtic</Typography>
<Typography sx={{ color: "rgb(108, 115, 127)" }}>
Some cool text here to represent out Backtick
</Typography>
</Box>
</LeftBox>
<RightBox>
<div>
<Box mb={"32px"}>
<Link to="/">
<img src={Logo} alt="Backtick Logo" width={140} />
</Link>
</Box>
</div>
<div>
<Stack direction="column" mb={"32px"}>
<Typography variant="h4" sx={{ color: "rgb(108, 115, 127)" }}>
Login
</Typography>
<Typography sx={{ color: "rgb(108, 115, 127)" }}>
Don't have an account? <Link to="/register">Register</Link>
</Typography>
</Stack>
<form onSubmit={formik.handleSubmit}>
<Stack direction="column">
<TextField
fullWidth
id="email"
name="email"
label="Email"
value={formik.values.email}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={formik.touched.email && Boolean(formik.errors.email)}
helperText={formik.touched.email && formik.errors.email}
/>
<TextField
fullWidth
id="password"
name="password"
label="Password"
type="password"
value={formik.values.password}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={
formik.touched.password && Boolean(formik.errors.password)
}
helperText={formik.touched.password && formik.errors.password}
sx={{ marginTop: "24px" }}
/>
</Stack>
<Button
color="primary"
variant="contained"
fullWidth
type="submit"
size="large"
sx={{ marginTop: "24px" }}
>
Submit
</Button>
</form>
</div>
</RightBox>
</LoginContainer>
);
};
export default Login;