如何用函数组件解决 React 中的不受控组件问题?
Posted
技术标签:
【中文标题】如何用函数组件解决 React 中的不受控组件问题?【英文标题】:How to solve Uncontrolled Component problem in React with Function Component? 【发布时间】:2021-12-19 06:44:42 【问题描述】:我正在制作表单组件。(它是功能组件)
它是不受控制的组件,因为我不想在Input
组件中进行不必要的渲染。
但它有一个意想不到的词。
我尝试在Input
组件中使用setState()
设置值并通过值道具onChange
。它不是将整个值从 Input
传递到 Form
我不想要不必要的渲染。但是,当我在电子邮件中输入值时,会同时使用密码对渲染做出反应。
我该如何解决这个问题?
代码沙盒链接 https://codesandbox.io/s/makewelldonecomponents-txxl0?file=/src/Input.js
或代码
(输入组件)
import React, useEffect, useState from "react";
const Input = ( type, placeholder, onChange ) =>
const [value, setValue] = useState("");
function handleChange(e)
setValue(e.target.value);
onChange(value);
return (
<>
console.log("render", placeholder)
<input placeholder=placeholder value=value onChange=handleChange />
</>
);
;
export default Input;
(表单组件)
import React, useState, useEffect from "react";
import Input from "./Input";
const Form = () =>
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [state, setState] = useState(0);
function handleSubmit(e)
e.preventDefault();
console.log(email, password);
function handleEmail(value)
setEmail(value);
console.log(value);
function handlePassword(value)
setPassword(value);
function handleReset(e)
setEmail("");
setPassword("");
setState(state + 1);
return (
<form onSubmit=handleSubmit>
<Input
key=state + "email"
type="email"
placeholder="이메일"
onChange=handleEmail
/>
<Input
key=state + "password"
type="password"
placeholder="비밀번호"
onChange=handlePassword
/>
<button type="submit">가입</button>
<button type="button" onClick=handleReset>
초기화
</button>
</form>
);
;
export default Form;
【问题讨论】:
【参考方案1】:-
在
Input
组件中使用useRef
而不是useState
。
import React, useRef from "react";
const Input = ( type, placeholder, onChange ) =>
const valRef = useRef("");
function handleChange(e)
valRef.current = e.target.value;
onChange(valRef.current);
return (
<>
console.log("render", placeholder)
<input
placeholder=placeholder
value=valRef.current
onChange=handleChange
/>
</>
);
;
export default Input;
-
使用
useCallback
到handleEmail
、handlePassword
函数
const handleEmail = useCallback((value) =>
setEmail(value);
console.log(value);
, []);
【讨论】:
感谢您的回答。我还有一个问题。当我第一次渲染组件时,useCallback 只渲染了一次。正确的?所以,你回答 Q2。但是,我用 useCallback 重写了我的代码,但在 handleEmail、handlePassword 中仍然是不必要的渲染。这是不可避免的工作吗?【参考方案2】:您可以在 React 中实现不受控制的表单,而无需使用状态和多个更改处理程序。
这是更新后的沙盒:
Form
组件:
const Form = () =>
const email = useRef(null);
const password = useRef(null);
function handleSubmit(e)
e.preventDefault();
console.log(email.current.value, password.current.value);
return (
<form onSubmit=handleSubmit>
<Input type="email" placeholder="이메일" ref=email />
<Input type="password" placeholder="비밀번호" ref=password />
<button type="submit">가입</button>
<button type="reset">초기화</button>
</form>
);
;
export default Form;
Input
组件:
import React, forwardRef from "react";
const Input = forwardRef((props, ref) =>
return <input ...props ref=ref />;
);
【讨论】:
好答案。但是,我需要了解 Q2。当我输入电子邮件或密码时,如何知道只渲染一个组件? @Aaaaaa 在上面的实现中,输入电子邮件/密码时没有重新渲染任何输入组件以上是关于如何用函数组件解决 React 中的不受控组件问题?的主要内容,如果未能解决你的问题,请参考以下文章
React面向组件编程 - 基本理解和使用 - 组件三大核心属性state-props-refs - 事件处理 - 非受控组件 - 受控组件 - 高阶函数 - 函数柯里化