【发布时间】:2019-06-20 22:27:24
【问题描述】:
我试图弄清楚受控和不受控的反应组件之间的区别,所以我想我会尝试构建一个可以是其中一个但不能同时是两者的控件。 <input> 使用的模式似乎是,如果您提供 value 道具,那么它将受到控制,否则不受控制,您可以使用 defaultValue 道具为不受控制提供默认值。
我的示例控件是一个简单的数字递增器/递减器,带有用于递增和递减的按钮以及显示当前值的标签。
我的问题是。
- 我是否以正确的方式解决了这个问题。
- 我已经编写了许多测试来涵盖我能想到的所有场景,这些都是有效的吗?我是否遗漏了任何一个。
我希望通过这个示例和任何反馈来彻底了解受控与非受控,以及何时使用它们。
我的代码和所有测试都在这个代码框https://codesandbox.io/s/kind-archimedes-cs0qy中可用
但我的组件在这里重复了方便...
import React, { useState } from "react";
export const NumberInput = ({ onChange, value, defaultValue, min, max }) => {
const [uncontrolledVal, setUncontrolledVal] = useState(
defaultValue || min || 0
);
if (
(value && (value > max || value < min)) ||
(defaultValue && (defaultValue > max || defaultValue < min))
) {
throw new Error("Value out of range");
}
const handlePlusClick = () => {
if (value && onChange) {
onChange(value + 1);
} else {
const newValue = uncontrolledVal + 1;
setUncontrolledVal(newValue);
if (onChange) {
onChange(newValue);
}
}
};
const handleMinusClick = () => {
if (value && onChange) {
onChange(value - 1);
} else {
const newValue = uncontrolledVal - 1;
setUncontrolledVal(newValue);
if (onChange) {
onChange(newValue);
}
}
};
return (
<>
<button
data-testid="decrement"
disabled={value ? value === min : uncontrolledVal === min}
onClick={() => handleMinusClick()}
>
{"-"}
</button>
<span className="mx-3 font-weight-bold">{value || uncontrolledVal}</span>
<button
data-testid="increment"
disabled={value ? value === max : uncontrolledVal === max}
onClick={() => handlePlusClick()}
>
{"+"}
</button>
</>
);
};
【问题讨论】:
-
它很简单:
controlled输入是由你完全控制的,你处理每一个变化,这就是为什么你需要通过value和onChange。value将代表正在屏幕上呈现的内容(可能是来自您的状态的值或来自容器的道具)和onChange来处理每个更改,因此您选择更新传递给value的状态。在uncontrolled上,您只需要通过defaultValue设置初始值并在需要时获取该值,您不关心它的更改以及它们的处理方式。 -
好吧,我想我明白了,我的示例组件可以满足两者,但是什么时候可以使用不受控制的控制?
-
假设我们有一个包含一些非常开放的输入的表单,我们不需要事先验证它们,然后我们可以将所有输入保持为不受控制,并在用户提交时获取值形式。例如,如果有一个名为“Name”的字段,我们不需要关心该字段内发生的每一个变化,只关心最终值。使用不受控制的代码会使代码更小一些,并且避免为您的输入编写句柄函数。也就是说,有时这只是个人选择使用什么。我个人更喜欢使用受控输入,但这是我的选择。
标签: reactjs