如何使用ReactJS获取输入字段的值?

我有以下反应组件:

导出默认类MyComponent扩展了React.Component{
提交(e){
e、 预防默认值();
var title=this.title;
控制台日志(标题);
}
render(){
返回(

<form className=“form horizontal”>

<input type=“text”className=“form control”ref={(c)=>this.title=c}name=“title”/>

</form>

<button type=“button”onClick={this.onSubmit}className=“btn”>保存</button>

);
}
};

控制台给了我未定义的-你知道这个代码有什么问题吗

这里有三个答案,这取决于你(被迫)使用的React版本,以及你是否想使用钩子

第一件事:

理解React是如何工作的很重要,这样你才能正确地做事(protip:React网站上的React教程练习非常值得一读。它写得很好,涵盖了所有的基础知识,以实际解释如何做事)。这里的“正确”表示您正在编写一个应用程序界面,该界面恰好在浏览器中呈现;所有的界面工作都发生在React中,而不是“如果你在写网页,你习惯了什么”(这就是React应用程序是“应用程序”,而不是“网页”的原因)

React应用程序的呈现基于以下两个方面:

  1. 由创建该组件实例的父级声明的组件属性,父级可以在其整个生命周期中修改该组件的实例,以及
  2. 组件自身的内部状态,它可以在其整个生命周期中修改自身

当您使用React时,您明确地没有做的是生成HTML元素,然后使用这些元素:当您告诉React使用<输入&gt,例如,您正在创建一个HTML输入元素,您正在告诉React创建一个React输入对象,该对象恰巧以HTML输入元素的形式呈现,其事件处理查看HTML元素的输入事件,但不受其控制

使用React时,您要做的是生成应用程序UI元素,向用户呈现(通常可操作)数据,用户交互会更改组件的状态,这可能会导致重新呈现部分应用程序界面以反映新状态。在此模型中,状态始终是最终权限,而不是“用于呈现它的任何UI库”,它在web上是浏览器的DOM。DOM在这个编程模型中几乎是事后才想到的:它只是React碰巧使用的特定UI框架

因此,对于输入元素,逻辑是:

  1. 键入输入元素
  2. 您的输入元素尚未发生任何变化,事件被React拦截并立即终止
  3. React将事件转发到您为事件处理设置的函数
  4. 该函数可以调度状态更新
  5. 如果是,React将运行该状态更新(异步!),并在更新后触发render调用,但仅当状态更新更改了状态时
  6. 只有在完成此渲染后,UI才会显示您“键入了一封信”

所有这些都发生在几毫秒之内,如果不是更短的话,那么它看起来就像你在输入元素中键入的方式与“在页面上仅使用输入元素”相同,但绝对不是这样

因此,关于如何从React中的元素中获取值:

反应15及以下,使用ES5

为了正确地执行操作,您的组件有一个状态值,它通过输入字段显示,我们可以通过让UI元素将更改事件发送回组件来更新它:

var Component=React.createClass({
getInitialState:函数(){
返回{
输入值:“”
};
},
render:function(){
返回(
//...
<输入值={this.state.inputValue}onChange={this.updateInputValue}/>
//...
);
},
updateInputValue:函数(evt){
这是我的国家({
输入值:evt.target.value
});
}
});

因此,我们告诉React使用updateInputValue函数来处理用户交互,使用setState来计划状态更新,而render点击this.state.inputValue这一事实意味着,当它在更新状态后重新启动时,用户将根据键入的内容查看更新文本

基于评论的附录

假设UI输入表示状态值(考虑一下如果用户中途关闭选项卡,并且选项卡被恢复,会发生什么情况。他们填写的所有值都应该恢复吗?如果是,这就是状态)。这可能会让你觉得一个大表单需要几十个甚至一百个输入表单,但React是以一种可维护的方式对你的UI建模:你没有100个独立的输入字段,你有一组相关的输入,所以你在一个组件中捕获每个组,然后将你的“主”表单构建为一个组的集合

MyForm:
提供:
<个人数据/>
<AppPreferences/>
<第三方/>
...

这也比一个巨大的单一表单组件更容易维护。将组拆分为具有状态维护的组件,其中每个组件一次只负责跟踪几个输入字段

您可能还觉得编写所有这些代码是“一件麻烦事”,但这是一个错误的节省:不是您的开发人员,包括未来的您,实际上从看到所有这些输入显式连接中获益匪浅,因为它使代码路径更容易跟踪。但是,您始终可以进行优化。例如,您可以编写一个状态链接器

MyComponent=React.createClass({
getInitialState(){
返回{
firstName:this.props.firstName | |“”,
lastName:this.props.lastName | |“
...: ...
...
}
},
组件willmount(){
Object.keys(this.state).forEach(n=&gt{
设fn=n+‘改变’;
此[fn]=evt=&gt{
让update={};
更新[n]=evt.target.value;
此.setState(更新);
});
});
},
render:function(){
返回Object.keys(this.state).map(n=&gt{
<输入
键={n}
type=“text”
值={this.state[n]}
onChange={this[n+'Changed']}/>
});
}
});

当然,这有改进的版本,所以请点击https://npmjs.com 并搜索您最喜欢的React-state链接解决方案。开源主要是寻找其他人已经做过的事情,并使用它们,而不是自己从头开始编写

反应16(和15.5过渡)和“现代”JS

从React 16开始(从15.5开始为软启动),不再支持createClass调用,需要使用类语法。这改变了两件事:明显的类语法,以及createClass可以“免费”执行的This上下文绑定,因此为了确保事情仍然有效,请确保在处理程序中为This上下文保护匿名函数使用“胖箭头”符号,例如我们在这里的代码中使用的onChange

类MyComponent扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
输入值:“”
};
}
render(){
返回(
//...
<输入值={this.state.inputValue}onChange={evt=>this.updateInputValue(evt)}/>
//...
);
},
更新输入值(evt){
这是我的国家({
输入值:evt.target.value
});
}
});

您可能还看到人们在构造函数中为所有事件处理函数使用bind,如下所示:

构造函数(道具){
超级(道具);
this.handler=this.handler.bind(this);
...
}
render(){
返回(
...
<element onclick={this.handler}/>
...
);
}

不要那样做

几乎在您使用bind的任何时候,“您做错了”这句谚语都适用。您的类已经定义了对象原型,因此已经定义了实例上下文。不要把bind放在上面;使用普通事件转发,而不是复制构造函数中的所有函数调用,因为这种复制会增加错误的表面,并使跟踪错误变得更加困难,因为问题可能在构造函数中,而不是在调用代码的地方。以及将维护负担强加给你(拥有或选择)与之共事的其他人

是的,我知道医生说没事。不是,不要这样做

反应16.8,使用带挂钩的功能部件

从React 16.8开始,通过使用钩子,函数组件(即,实际上只是一个将一些道具作为参数的函数,可以像组件类的实例一样使用,而无需编写类)也可以被赋予状态

如果您不需要完整的类代码,而只需要一个实例函数,那么现在可以使用useState钩子获取一个状态变量及其更新函数,其工作原理与上述示例大致相同,只是没有setState函数调用:

从“react”导入{useState};
函数myFunctionalComponentFunction(){
const[input,setInput]=useState(“”);/“”是初始状态值
返回(
<div>
<label>请指定:</label>
<input value={input}onInput={e=>setInput(e.target.value)}/>
</div>
);
}

p

发表评论