我在 styled-component 中使用 ReactBootstrap ,在 Context 中存储 formData
我希望 Form.Control 保持其原始样式,并仅在我第一次输入后才开始检查验证。
当我更改名称和帐户时,反馈div可以正常工作,
但是当我 onChange password 和 informPassword 时,它们的反馈 div 渲染不会随 onChange 事件更新。
上下文正确,但渲染不正确,
我知道 setState 意味着在下一个渲染中更新,但我的 informCheck 也是一个状态?
我该如何解决这个问题
FormContainer.jsx
import { useState } from "react";
import Form from "react-bootstrap/Form";
function FormContainer({ children, handleSubmitExtend }) {
const [validated, setValidated] = useState(false);
const handleSubmit = (event) => {
const form = event.currentTarget;
console.log("組件", form);
event.preventDefault();
event.stopPropagation();
setValidated(true);
handleSubmitExtend();
};
return (
<Form noValidate validated={validated} onSubmit={handleSubmit}>
{children}
</Form>
);
}
export default FormContainer;
表单输入.jsx
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";
import Form from "react-bootstrap/Form";
import { useEffect, useState } from "react";
export default function FormInput({
label,
type,
value,
placeholder,
onChange,
invalidPrompt,
minlength,
maxlength,
confirmCheck = true,
}) {
const handleFormChange = (e) => {
const inputNode = e.target;
if (inputNode.validity.valid && confirmCheck) {
inputNode.classList.remove("is-invalid");
inputNode.classList.add("is-valid");
} else {
inputNode.classList.add("is-invalid");
inputNode.classList.remove("is-valid");
}
};
return (
<Row>
<Form.Group as={Col} md="12">
<Form.Label htmlFor={label}>{label}</Form.Label>
<Form.Control
className="mb-3 input-rows"
id={label}
required
type={type}
placeholder={placeholder}
defaultValue={value}
value={value}
onChange={(e) => {
onChange?.(e.target.value);
handleFormChange(e);
}}
minLength={minlength}
maxLength={maxlength}
/>
<Form.Control.Feedback>OK!</Form.Control.Feedback>
<Form.Control.Feedback type="invalid">
{invalidPrompt}
</Form.Control.Feedback>
</Form.Group>
</Row>
);
}
注册页面.jsx
import styled from "styled-components";
import { useEffect, useState } from "react";
import { useAuth } from "../context/AuthContext";
import Swal from "sweetalert2";
import FormContainer from "../components/AuthForm/FormContainer";
import FormInput from "../components/AuthForm/FormInput";
export default function RegisterPageTest() {
const defaultForm = {
account: "",
password: "",
confirmPassword: "",
name: "",
};
const [form, setForm] = useState(defaultForm);
const [confirmCheck, setConfirmCheck] = useState(true);
const handleInputOnchange = (attr, inputValue) => {
setForm({
...form,
[attr]: inputValue,
});
setConfirmCheck(form.password === form.confirmPassword);
};
const { login, isLogin } = useAuth();
const handleSubmit = async () => {
const { name, account, password, confirmPassword } = form;
console.log(name, account);
if (
name.length < 2 ||
account.length < 4 ||
password.length < 4 ||
confirmPassword.length < 4
) {
Swal.fire({
title: "error",
text: "Error",
icon: "question",
});
return;
}
try {
const status = await login(form);
if (status === "success") {
Swal.fire({
title: "success!",
text: "success",
icon: "success",
});
} else {
Swal.fire({
title: "註冊失敗!",
button: "好",
icon: "success",
});
}
} catch (error) {
console.log(error);
}
};
return (
<AuthPage>
<AuthContainer>
<FormContainer handleSubmitExtend={handleSubmit}>
<AuthTitle>Sign up for free </AuthTitle>
<FormInput
key={form}
label="account"
type="text"
placeholder="account"
value={form.account}
onChange={(inputValue) =>
handleInputOnchange("account", inputValue)
}
invalidPrompt={"At least 4 or more characters"}
minlength={4}
maxlength={16}
></FormInput>
<FormInput
key={form}
label="password"
type="password"
placeholder="password..."
value={form.password}
onChange={(inputValue) =>
handleInputOnchange("password", inputValue)
}
invalidPrompt={"At least 4 or more characters"}
minlength={4}
maxlength={16}
confirmCheck={confirmCheck}
></FormInput>
<FormInput
key={form}
label="confirmPassword"
type="password"
placeholder="confirmPassword"
value={form.confirmPassword}
onChange={(inputValue) =>
handleInputOnchange("confirmPassword", inputValue)
}
invalidPrompt={
form.confirmPassword !== form.password
? "password doesn't match"
: "At least 4 or more characters"
}
confirmCheck={confirmCheck}
minlength={4}
maxlength={16}
></FormInput>
<FormInput
key={form}
label="用戶名稱"
type="text"
placeholder="username..."
value={form.name}
onChange={(inputValue) => handleInputOnchange("name", inputValue)}
invalidPrompt={"At least 1 or more characters"}
minlength={1}
maxlength={16}
></FormInput>
<AuthButton>註冊</AuthButton>
<AuthLink>
已經有帳號了? <a href="/login">登入</a>
</AuthLink>
</FormContainer>
</AuthContainer>
<AuthBanner>大圖片</AuthBanner>
</AuthPage>
);
}
const AuthPage = styled.div`
width: 100%;
height: 100%;
display: flex;
flex-direction: row;
`;
const AuthContainer = styled.div`
background-color: ${({ theme }) => theme.containerBackground};
display: flex;
flex-wrap: wrap;
flex-direction: column;
justify-content: center;
align-items: center;
width: 50%;
margin-top: 120px;
`;
const AuthBanner = styled.div`
display: flex;
width: 50%;
flex-wrap: wrap;
flex-direction: column;
justify-content: center;
align-items: center;
`;
const AuthButton = styled.button`
border-radius: 5px;
background-color: #217c4a;
border: none;
cursor: pointer;
color: white;
min-width: 300px;
font-family: "Noto Sans TC", sans-serif;
font-weight: bold;
padding: 6px 0;
margin: 2rem 0;
&.hover {
cursor: pointer;
}
`;
const AuthTitle = styled.div`
width: 100%;
text-align: center;
font-size: 24px;
font-weight: bold;
text-align: start;
`;
const AuthLink = styled.div`
width: 100%;
display: flex;
justify-content: center;
text-align: center;
`;
我尝试过useEffect,但它也不起作用,我尝试了4个多小时......
我不知道这是否是一个好方法。
我使用 DOM 作为当前值并更新 DOM
const checkConfirm = () => {
const password = document.querySelector("#password");
const confirmPassword = document.querySelector("#confirmPassword");
console.log(password.value ,confirmPassword.value)
if (password.value === confirmPassword.value) {
password.classList.remove("is-invalid");
password.classList.add("is-valid");
confirmPassword.classList.remove("is-invalid");
confirmPassword.classList.add("is-valid");
} else {
password.classList.add("is-invalid");
password.classList.remove("is-valid");
confirmPassword.classList.add("is-invalid");
confirmPassword.classList.remove("is-valid");
}
};