【发布时间】:2021-07-27 14:13:42
【问题描述】:
我有一个简单的 for,其中包含一些字段,这些字段是该表单的子组件。每个字段都验证自己的值,如果它发生变化,它应该向父级报告,这会导致字段重新渲染并失去焦点。我想要一个子组件不更新的行为。这是我的代码:
父(表单):
function Form() {
const [validFields, setValidFields] = useState({});
const validateField = (field, isValid) => {
setValidFields(prevValidFields => ({ ...prevValidFields, [field]: isValid }))
}
const handleSubmit = (event) => {
event.preventDefault();
//will do something if all fields are valid
return false;
}
return (
<div>
<Title />
<StyledForm onSubmit={handleSubmit}>
<InputField name="fooField" reportState={validateField} isValidCondition={fooRegex} />
<Button type="submit" content="Enviar" maxWidth="none" />
</StyledForm>
</div>
);
}
export default Form;
子(字段):
function InputField(props) {
const [isValid, setValid] = useState(true);
const [content, setContent] = useState("");
const StyledInput = isValid ? Input : ErrorInput;
const validate = (event) => {
setContent(event.target.value);
setValid(stringValidator.validateField(event.target.value, props.isValidCondition))
props.reportState(props.name, isValid);
}
return (
<Field>
<Label htmlFor={props.name}>{props.name + ":"}</Label>
<StyledInput
key={"form-input-field"}
value={content}
name={props.name}
onChange={validate}>
</StyledInput>
</Field>
);
}
export default InputField;
通过为我的子元素设置key,我能够防止它在内容更改时失去焦点。我想我想将shouldComponentUpdate 实现为stated in React documentation,并尝试通过执行以下操作来实现它:
尝试 1:用 React.memo 包围孩子
const InputField = React.memo((props) {
//didn't change component content
})
export { InputField };
尝试 2:用 useMemo 在父母身上勾引孩子
const fooField = useMemo(<InputField name="fooField" reportState={validateField} isValidCondition={fooRegex} />, [fooRegex]);
return (
<div>
<Title />
<StyledForm onSubmit={handleSubmit}>
{fooField}
<Button type="submit" content="Enviar" maxWidth="none" />
</StyledForm>
</div>
);
两者都不起作用。 如何才能让子组件在isValid状态发生变化时不重新渲染?
【问题讨论】:
-
字段在重新渲染时不会“失去焦点”,但在“重新安装”时可能会失去焦点,但不确定。你找错树了。编辑:您看起来好像正在通过这条线重新安装:
const StyledInput = isValid ? Input : ErrorInput;。解决方案是不要重新安装。我想到的第一个解决方案是将Input和ErrorInput组合成一个组件,如果可能的话,用prop控制样式。你能发布这两个组件吗? -
确实:您正在根据字段是否有效呈现两个完全独立的组件。这种方法将导致您描述的所有问题。使用单个 Input 并更改其样式。
-
@Adam 我不敢相信我没有早点意识到这一点。你完全正确。随时发表您的评论作为答案。我很乐意接受它。
-
学习并使用useMemo进行记忆
-
@William 添加了一个答案,但我看到了其他可疑的东西。您正在调用
reportState并在本地存储isValid。您是否 100% 确定这是您的表单框架的工作方式?是否有一个道具可以用来告诉您该字段是否有效而不将其存储为本地状态?通常,后者是大多数表单框架的工作方式,因此您永远不应该真正拥有isValid的本地状态,而应该“来自上方”
标签: javascript reactjs react-hooks