React受控组件和不受控组件是什么?

266

在ReactJS中,什么是受控组件和非受控组件?它们之间有何不同之处?

9个回答

357

这与有状态的DOM组件(表单元素)有关,React文档解释了其中的区别:

  • 一个受控组件通过 props 来取得其当前值,并通过诸如 onChange 的回调通知更改。父组件通过处理回调并管理自己的状态,将新值作为 props 传递给受控组件来“控制”它。你也可以称之为“哑组件”。
  • 一个非受控组件是一种在内部存储自己状态的组件,当需要时,您使用 ref 查询 DOM 来查找其当前值。这有点类似于传统的 HTML。

大多数本地 React 表单组件都支持受控和非受控用法:

// Controlled:
<input type="text" value={value} onChange={handleChange} />

// Uncontrolled:
<input type="text" defaultValue="foo" ref={inputRef} />
// Use `inputRef.current.value` to read the current value of <input>

在大多数(或所有)情况下,您应该使用受控组件


4
取值不是通过 props,而是通过 state 吗? - Ivanka Todorova
26
对于受控组件,值通过 props 传递。而不受控制的组件则使用 state 在内部控制值本身。这是关键区别。 - Aaron Beall
7
它们之间的区别在于,值被设置/传递并具有回调函数的组件被称为“受控组件”(<input type="text" value="value" onChange={handleChangeCallbackFn} />),而传统的HTML中,输入元素处理自己的值,并且可以通过称为“未受控组件”的refs进行读取(<value type="text" />)。受控组件通过setState管理自身状态或从其父组件作为属性获取状态。 - Lior Elrom
1
一个不需要任何属性或没有任何状态的组件也是一个未受控制的组件。 - sujeet
2
这个答案不准确,也没有反映出它链接到的文档中的信息。Control并不是指父组件通过props来管理子组件,而是表单数据是使用React状态来管理的。一个不受控制的组件的表单数据由DOM管理,类似于普通的HTML表单(在React中通过使用refs实现)。 - ElwoodP
显示剩余10条评论

96

它们都渲染表单元素

Uncontrolled componentControlled component 是用于描述渲染 HTML 表单元素 的 React 组件的术语。每次你创建一个渲染 HTML 表单元素的 React 组件时,你就创建了其中之一。

Uncontrolled componentControlled component 在访问表单元素 (<input>, <textarea>, <select>) 中的数据的方式上有所不同。

Uncontrolled Components

未受控制的组件 是指渲染表单元素的组件,其中表单元素的数据由 DOM 处理(默认 DOM 行为)。要访问输入框的 DOM 节点并提取其值,可以使用 ref

示例 - 未受控制的组件:
const { useRef } from 'react';

function Example () {
  const inputRef = useRef(null);
  return <input type="text" defaultValue="bar" ref={inputRef} />
}

受控组件

一个 受控组件 是指渲染表单元素并通过将表单数据存储在组件状态中来控制它们的组件。

受控组件 中,表单元素的数据由 React 组件(而不是 DOM)处理并保存在 组件状态 中。受控组件基本上重写了 HTML 表单元素的默认行为。

我们通过设置其属性 value 和事件 onChange 将表单元素 (<input>, <textarea><select>) 与 state 相连来创建受控组件。

例子 - 受控组件:
const { useState } from 'react';

function Controlled () {
  const [email, setEmail] = useState();

  const handleInput = (e) => setEmail(e.target.value);


  return <input type="text" value={email} onChange={handleInput} />;
}

7
好的,我会尽力进行翻译。以下是需要翻译的内容:我认为这个答案比被采纳的更好。让我的想法更清晰了。上面那个对我来说有点困惑。我的翻译如下:我觉得这个答案比被采纳的那个更好。它让我想法更加清晰了。被采纳的那个对我来说有点难以理解。 - Maddy8381
1
这绝对是我遇到的最好、最直接的答案了.. 谢谢 @ross_u! - Ankit_M
2
@Maddy8381 接受的答案并不正确。受控组件与通过props由其父组件管理无关。它指的是表单数据由React状态管理,就像这个答案所描述的那样。 - ElwoodP
@ElwoodP 我认为你的理解是相反的。受控组件与父组件如何管理状态无关,它可能在父组件的状态中,也可能在更上层,也可能在Redux中,或者其他状态管理策略中...... “受控”方面是指表单元素组件没有自己的状态,并由外部props控制。 - Aaron Beall
@AaronBeall,非常抱歉,我犯了一个错误。我同意你所说的是正确的。 - ElwoodP

9

被控制的组件是从回调函数获取更改值的组件,而不受控制的组件是具有来自DOM的值的组件。

例如,当输入值改变时,我们可以在受控制的组件中使用onChange函数来获取值,也可以像ref一样使用DOM来获取值。


8

受控组件:表单数据由React组件处理。

在ReactJS中受控组件的流程 图片

非受控组件:表单数据由DOM本身处理。

在ReactJS中非受控组件的流程 图片


5
简述;

https://www.youtube.com/watch?v=6L2Rd116EvY 你可以查看这个页面,他很好地解释了它......

受控组件

不用复杂的词语,受控组件是渲染表单元素(如<input/>)的组件,其值由React独自控制。例如,复制下面的代码并尝试更改DOM中的输入字段...

export default function Component() {

  return (
        <div>
            <input type="text" value="somevalue" />
            
          </div>
)
}

无论您尝试多少次更新上述输入的值,React 都不会让您成功。因为 React 希望使用状态控制更新后的值,这就是标题“受控”的含义...可以通过将属性 onChange 和 value 与状态连接起来并按以下示例进行尝试更新其值。
function Component() {

  const [text,setText] = React.useState("")

  return (
          <div>

            <input type="text" onChange={(e)=>setText(e.target.value)} value={text} />

            <p>{text}</p> 
          </div>
  )
}

现在我们的输入可以被更新,它的值可以用于渲染或者执行即时验证......

非受控组件

非受控组件是渲染表单元素(比如 <input/>)的组件,其值可以由 Dom 元素处理。而受控和非受控之间的一个主要区别就是 value 属性的定义。对于非受控组件,我们使用 defaultValue 或者有时候根本没有值。

function Component() {

  return (
         <div>

            <input type="email" id="message" defaultValue="example@mail.com" />
            
          </div>
  )
}

上述输入框的值可以通过DOM进行更改控制,无需使用React...

建议在React中更多地使用受控组件,因为您可以执行即时验证并强制实现动态输入。


4

受控组件不持有它们的状态。

所需数据从父组件传递给它们。

它们通过回调函数与该数据交互,这些回调函数也是从父组件传递给子组件的。


2

控制组件是React中推荐的一种做法。

它允许我们将所有组件状态都保存在React状态中,而不是依靠DOM通过其内部状态获取元素的值。

控制组件是从状态派生其输入值的组件。


1
根据文档
受控组件中,表单数据由React组件处理。
另一种选择是非受控组件,其中表单数据由DOM本身处理。

1

受控组件主要是指组件的任何属性值都来自于父组件或存储中的值(例如redux中的情况)。例如:

<ControlledComp value={this.props.fromParent}/>

在无控制组件的情况下,组件的值可以根据事件处理从组件的状态中获取。例如:

<UncontrolledComp value={this.state.independentValue}/>

10
这并没有解释清楚这个概念。请参考其他回答或者干脆删除这个回答。 - salvi shahzad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接