表单在React里的高级运用和select状态提升【高级React技术】

简介: 表单在React里的高级运用和select状态提升【高级React技术】

@[toc]

表单

在React中,HTML表单元素的工作方式与其他DOM元素不同,因为表单元素通常维护一些内部状态。例如,此纯HTML表单只接受一个名称:

<form>
  <label>
    名字:
    <input type="text" name="name" />
  </label>
  <input type="submit" value="提交" />
</form>

此表单具有默认的HTML表单行为,即在用户提交表单后浏览到一个新页面。如果在React中执行相同的代码,它仍然有效。然而,在大多数情况下,使用JavaScript函数来处理表单提交以及访问用户填写的表单数据是非常方便的。实现这种效果的标准方法是使用“受控组件”。

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('提交的名字: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          名字:
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="提交" />
      </form>
    );
  }
}

由于value属性是在表单元素上设置的,因此显示的值将始终为this。state Value,这使得React的状态成为唯一的数据源。因为handlechange在每次按下键时都会执行并更新React的状态,所以显示的值将在用户输入时更新。

class EssayForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: '请撰写一篇关于你喜欢的 DOM 元素的文章.'
    };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('提交的文章: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          文章:
          <textarea value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="提交" />
      </form>
    );
  }
}

对于受控组件,输入值始终由React状态驱动。您还可以将值传递给其他UI元素,或通过其他事件处理函数重置它,但这意味着您需要编写更多代码。

select

在HTML中,<select>创建一个下拉列表标记。例如,以下HTML创建了一个与水果相关的下拉列表:

<select>
  <option value="grapefruit">葡萄柚</option>
  <option value="lime">酸橙</option>
  <option selected value="coconut">椰子</option>
  <option value="mango">芒果</option>
</select>

请注意,由于选定的属性,默认情况下会选择椰子选项。React不使用所选属性。相反,它使用根选择标记上的value属性。这在受控组件中更方便,因为您只需要在根标记中更新它。

class FlavorForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: 'coconut'};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('你喜欢的风味是: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          选择你喜欢的风味:
          <select value={this.state.value} onChange={this.handleChange}>
            <option value="grapefruit">葡萄柚</option>
            <option value="lime">酸橙</option>
            <option value="coconut">椰子</option>
            <option value="mango">芒果</option>
          </select>
        </label>
        <input type="submit" value="提交" />
      </form>
    );
  }
}

状态提升

通常,多个组件需要反映相同的更改数据。此时,我们建议将共享状态提升到最近的公共父组件。让我们看看它是如何工作的。

function BoilingVerdict(props) {
  if (props.celsius >= 100) {
    return <p>The water would boil.</p>;
  }
  return <p>The water would not boil.</p>;
}

在本节中,我们将创建一个温度计算器来计算水在给定温度下是否沸腾。
我们将从一个名为BoilingVerdict的组件开始,它接受摄氏温度作为一个参数,并打印温度是否足以使水沸腾的结果。

class Calculator extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.state = {temperature: ''};
  }

  handleChange(e) {
    this.setState({temperature: e.target.value});
  }

  render() {
    const temperature = this.state.temperature;
    return (
      <fieldset>
        <legend>Enter temperature in Celsius:</legend>
        <input
          value={temperature}
          onChange={this.handleChange} />
        <BoilingVerdict
          celsius={parseFloat(temperature)} />
      </fieldset>
    );
  }
}

接下来,我们创建一个名为Calculator的组件。它为输入温度渲染一个<input>,并将其值保存在其中。状态温度。
此外,它还基于当前输入值渲染BoilingVerdict组件。

上述两个函数仅执行数值转换。相反,我们将编写另一个函数,接受字符串类型的温度和转换函数作为参数并返回字符串。我们将使用它根据另一个输入框的值来计算一个输入盒的值。
当输入温度值无效时,函数返回空字符串;否则,返回保留三位小数并四舍五入的转换结果:

我们现在有两个输入框,但当您在其中一个输入框中输入温度时,另一个将不会更新。这与我们的要求相矛盾:我们希望它们保持同步。
此外,我们无法通过Calculator组件显示BoingVerdict组件的渲染结果。因为计算器组件不知道TemperatureInput组件中隐藏的当前温度。

function tryConvert(temperature, convert) {
  const input = parseFloat(temperature);
  if (Number.isNaN(input)) {
    return '';
  }
  const output = convert(input);
  const rounded = Math.round(output * 1000) / 1000;
  return rounded.toString();
}

但是,我们希望两个输入框中的值彼此同步。当我们更新摄氏度输入框中的值时,华氏度输入框应显示转换后的华氏温度,反之亦然。
在React中,要在多个组件之间共享的状态可以通过将其移动到最近的公共父组件来共享。这被称为“国家提升”。接下来,我们将把TemperatureInput组件中的状态移动到Calculator组件。

  render() {
    // Before: const temperature = this.state.temperature;
    const temperature = this.props.temperature;
    // ...

如果计算器组件具有共享状态,它将成为两个温度输入框中当前温度的“数据源”。它可以使两个温度输入框的值彼此一致。由于两个TemperatureInput组件的道具来自公共父组件Calculator,因此两个输入框的内容始终一致。

相关文章
|
2月前
|
移动开发 前端开发 JavaScript
React 表单与事件
10月更文挑战第10天
44 1
|
3月前
|
前端开发 JavaScript 网络架构
react对antd中Select组件二次封装
本文介绍了如何在React中对Ant Design(antd)的Select组件进行二次封装,包括创建MSelect组件、定义默认属性、渲染Select组件,并展示了如何使用Less进行样式定义和如何在项目中使用封装后的Select组件。
120 2
react对antd中Select组件二次封装
|
2月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
223 2
|
2月前
|
Rust 前端开发 JavaScript
前端技术新探索:从React到WebAssembly的高效之路
前端技术新探索:从React到WebAssembly的高效之路
89 1
|
15天前
|
存储 前端开发 JavaScript
React 表单输入组件 Input:常见问题、易错点及解决方案
本文介绍了在 React 中使用表单输入组件 `Input` 的基础概念,包括受控组件与非受控组件的区别及其优势。通过具体代码案例,详细探讨了创建受控组件、处理多个输入字段、输入验证和格式化的方法,并指出了常见易错点及避免方法,旨在提升表单的健壮性和用户体验。
27 4
|
2月前
|
前端开发 JavaScript 数据安全/隐私保护
深入探索研究React表单
【10月更文挑战第6天】
91 57
|
1月前
|
前端开发 JavaScript
React 表单处理技巧
【10月更文挑战第24天】本文从初学者角度出发,详细介绍了 React 中表单处理的基本概念、常见问题及解决方案。涵盖受控组件与非受控组件的区别、状态更新、表单验证、多字段管理及高级技巧,通过代码示例帮助读者更好地理解和应用。
81 7
|
2月前
|
前端开发 JavaScript 开发者
探索现代Web前端技术:React框架入门
【10月更文挑战第9天】 探索现代Web前端技术:React框架入门
|
3月前
|
前端开发
react动态生成input、select标签以及思路总结
本文介绍了在React中动态生成input和select标签的方法,包括准备数据结构、在组件挂载时动态添加状态、页面渲染以及输入处理,最后总结了实现思路。
40 1
react动态生成input、select标签以及思路总结
|
2月前
|
前端开发 数据安全/隐私保护
前端技术实战:React Hooks 实现表单验证
【10月更文挑战第1天】前端技术实战:React Hooks 实现表单验证