我有一个包含子组件的父组件。
子级包含多个表单元素,以及它们的状态和验证它们的函数。
父级有一个表单按钮,单击该按钮时会调用子级中实现的验证函数。
问题是,当提交时从父进程调用该函数时,该函数无法“看到”状态变量的当前值(它看到的是初始值)。
但是,当从子进程调用该函数时,它可以按预期看到当前值。
以下是 Parent 的实现:
type ValidatorRunner = () => boolean;
const Parent = () => {
const [ childValidator, setChildValidator ] = useState<ValidatorRunner>();
function validateChild(): boolean {
if (childValidator) return childValidator();
else return false;
}
const doSubmit = async (e: SyntheticEvent) => {
e.preventDefault();
const formData = new FormData(e.target as HTMLFormElement);
const formJson = Object.fromEntries(formData.entries());
if (validateChild()) {
console.log("[Parent]: Good to send data:\n" + JSON.stringify(formJson));
} else {
console.log("[Parent]: Can't send data (data not valid)");
}
};
return (
<div>
<form onSubmit={ doSubmit }>
<div>Parent</div>
<div><Child validatorSetter={ setChildValidator }/></div>
<div><button type='submit'>Submit</button></div>
</form>
</div>
);
};
这是孩子:
interface ChildProps {
text?: string,
validatorSetter?: (validator: () => ValidatorRunner) => void
}
const Child = ({text, validatorSetter}: ChildProps) => {
const [ textValue, setTextValue] = useState(text ?? "");
const [ textFeedback, setTextFeedback] = useState("");
useEffect(() => {
if (validatorSetter) {
validatorSetter(() => validate);
};
}, [validatorSetter]);
const validate = (): boolean => {
console.log("[Child]: validate " + textValue);
let isValidText: boolean = validateText(textValue);
return isValidText;
}
const validateText = (data: string): boolean => {
if (data.length === 0) {
setTextFeedback("The text can't be empty");
return false;
}
else {
setTextFeedback("");
return true;
}
};
const doChange = (e: ChangeEvent<HTMLInputElement>) => {
setTextValue(e.target.value);
validateText(e.target.value);
};
return (
<div style={{ border: '1px solid' }}>
<label htmlFor="text">Text: </label>
<input id="text" name='text' type='text' maxLength={ 16 } onChange={ doChange } value={ textValue }/>
<button type="button" onClick={ validate }>?</button>
<label> { textFeedback } </label>
</div>
);
};
单击[?](在 Child 中)将调用Child.validate()
,它会按预期将 的当前值打印Child.textValue
到控制台。
单击[Submit](在 Parent 中)将调用Child.validate()
,它会打印 的初始值Child.textValue
。
我该如何实现?我尝试过其他解决方案useRef
,例如useImperativeHandle
、等等,但无法在这种情况下实现。