如何在React中创建一个表单元素

276 阅读6分钟

前面的教程向我们介绍了在React中创建组件以及在这些组件中使用状态和道具。到目前为止,这些组件都是基于函数的。现在我们想看看如何在React中使用类的语法来创建组件。在React中,你可以使用有状态的函数或者使用类组件来完成同样类型的事情。你选择哪种方法取决于你。使用钩子的函数组件目前似乎非常流行,但我们仍然想知道基于类的React语法是怎么回事,所以让我们使用类的语法建立一些组件。


基于类的React组件

我们可以做的第一件事是将App函数组件转换为类组件。你定义一个同名的类,并让它扩展React中的一个特殊类,即 React.Component类。通过扩展 React.Component你让你的App JavaScript类成为正式的React组件。就像函数组件一样,类组件也将数据映射到视图。然而现在,这个简单的App组件已经足够了。它只是我们应用程序的占位符。

class App extends React.Component {
	render() {
  	return (
    	<div>

    	</div>
    );
  }	
}

在React中创建一个表单组件

在这个应用程序中,我们想用一个表单来捕获用户的一些输入数据。例如,我们想让用户选择一个公司名称,然后点击 "开始"。在这一点上,应用程序将从Githubrest api中获取该公司的详细信息,这样我们就可以在反应中处理这些数据了。所以,首先,这里是一个使用类语法的React的Form组件

class Form extends React.Component {
	render() {
  	return (
    	<form>
      <span className="formtext"><Form /></span>
    	  <input 
          type="text" 
          placeholder="Enter Company Name" 
          required 
        />
        <button>Go!</button>
    	</form>
    );
  }
}

为了使该组件呈现在页面上,我们可以简单地在App组件声明中添加一个对Form组件的引用。

class App extends React.Component {
	render() {
  	return (
    	<div>
        <Form />
    	</div>
    );
  }	
}

react class syntax form component

为了使页面上的每个组件更容易被视觉化,我们添加了一些简单的css样式,增加了一个带有文本的轮廓。

form {
  border: thin solid red;
  padding: 2rem;
  margin: 2rem;
  display: flex;
}

.formtext {
  position: relative;
  top: -48px;
  background: white;
  padding: 7px;
  width: 57px;
  color: red;
}

用onChange捕捉文本输入的状态

我们希望能够在React应用程序中使用文本输入中捕获的数据,但我们如何做到这一点?首先,让我们给Form组件添加一个 **state**对象到Form组件。我们将设置一个属性 **companyName**的一个属性为 "Microsoft"。

class Form extends React.Component {
  state = { companyName: 'Microsoft' };

	render() {
  	return (
    	<form>
      <span className="formtext"><Form /></span>
    	  <input 
          type="text" 
          value={this.state.companyName}
          placeholder="Enter Company Name" 
          required 
        />
        <button>Go!</button>
    	</form>
    );
  }
}

这样做的目的是渲染表单,并在文本输入中填入一个值。我们可以尝试在文本输入中输入一些东西,但你将不能这样做。目前,它是硬编码的。事实上,在安装了React Dev Tools之后,我们可以看到一条信息,上面写着 "警告。失败的道具类型。你为一个没有 "onChange "处理程序的表单字段提供了一个`value`道具。这将呈现一个只读的字段。如果该字段应该是可变的,请使用`defaultValue`。否则,设置`onChange`或`readOnly`。
react state from form text input

所以我们可以看到state.companyName的值是如何填充到文本表单中的。然而,我们希望这是动态的。我们希望能够通过简单地在文本输入中键入来设置状态。我们如何做到这一点呢?通过onChange处理程序。下面突出显示的一行将在用户向输入字段输入时设置state.companyName。

class Form extends React.Component {
  state = { companyName: '' };

	render() {
  	return (
    	<form>
      <span className="formtext"><Form /></span>
    	  <input 
          type="text" 
          value={this.state.companyName}
          onChange={event => this.setState({ companyName: event.target.value })}
          placeholder="Enter Company Name" 
          required 
        />
        <button>Go!</button>
    	</form>
    );
  }
}

使用onSubmit对捕获的数据进行操作

现在,当用户在文本输入框中输入文本时,状态会自动更新。现在我们想在用户点击 "开始 "时对这些数据进行操作。这样做的方法是建立一个事件处理函数,然后在用户点击按钮时引用该函数。因此,这里是我们将用于处理函数的代码。我们想使用companyName的值来向Github rest api发出一个获取请求。我们将使用axios库来实现这一点。

class Form extends React.Component {
  state = { companyName: '' };
    
  handleSubmit = async (event) => {
    event.preventDefault();
    const resp = await axios.get(`https://api.github.com/users/${this.state.companyName}`);
    this.props.onSubmit(resp.data);
    this.setState({ companyName: '' });
  };

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <span className="formtext"><Form /></span>
          <input 
            type="text" 
            value={this.state.companyName}
            onChange={event => this.setState({ companyName: event.target.value })}
            placeholder="Enter Company Name" 
            required 
          />
          <button>Go!</button>
        </form>
      );
    }
}

在上面的代码中,我们现在可以看到表单标签有一个onSubmit属性。该属性引用了 handleSubmit异步函数。我们需要包括event.preventDefault()来防止html表单试图提交自己。我们要做的就是捕获输入的数据并使用它。Axios被用来向Github api发出请求。因此,如果我们输入了 "Microsoft",那么请求就会转[到https://api.github.com/users/Microsoft。如果你把这个网址插入浏览器,你可以看到它产生的数据。
github rest api response

这就是我们想在React中使用的数据这里是稍微令人困惑的部分。注意this.props.onSubmit(resp.data);这行代码。我们在这里说的是,我们想从api调用中获取数据,并将其传递给onSubmit()函数。这个函数还不存在。事实上,如果我们在文本字段中输入一些东西并点击按钮,我们会得到一个错误,如 "未发现(在承诺中)类型错误。_this.props.onSubmit不是一个函数"。我们该如何解决这个问题呢?


通过道具传递函数

回顾一下,父组件可以通过props对象向子组件传递属性。这些属性可以是简单的原始值或函数引用。这意味着我们的App组件可以向Form组件传递一个函数引用,而Form组件将能够调用该函数,因为它将是其props对象的一部分。为了让我们能看到它的作用,我们现在将在App组件中定义一个叫做doSomething()的函数。我们想让它做的就是注销传递给它的数据。所以请注意这个函数的定义,同样重要的是,我们使用

.

class App extends React.Component {

  doSomething = (companyinfo) => {
    console.log(companyinfo);
  };
  
	render() {
  	return (
    	<div>
        <Form onSubmit={this.doSomething} />
    	</div>
    );
  }	
}

现在我们可以看到,通过点击表单上的按钮,我们向Github发出了一个成功的api请求,并将数据记录到了控制台。非常酷


一个简单的React.js表单实例总结

在本教程中,我们学习了一些关于如何在React中创建一个表单元素,以及如何对我们捕获的数据采取行动。要创建一个React类组件,请扩展React.Component类。为了将表单组件的状态与表单输入联系起来,我们可以使用onChange处理程序。通过通过props对象传递一个函数,我们可以对从api请求回来的数据做一些处理。接下来,我们将看到如何使用React中的额外组件来获取api响应数据并在浏览器中显示它。