我有以下React组件:
export default class MyComponent extends React.Component {
onSubmit(e) {
e.preventDefault();
var title = this.title;
console.log(title);
}
render(){
return (
...
<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">Save</button>
...
);
}
};
控制台正在给我undefined
- 任何想法这个代码有什么问题?
答案 0 :(得分:182)
这里有三个答案,具体取决于您使用的React的版本(强制),以及是否要使用钩子。
了解React的工作方式非常重要,因此您可以正确地做事(protip:它的超级值得在React网站上运行React教程练习。它编写得很好,并以实际解释如何做事的方式涵盖所有基础知识。 &#34;妥&#34;这意味着您正在编写恰好在浏览器中呈现的应用程序界面;所有界面工作都在React中进行,而不是在&#34;您已经习惯了如果您正在编写网页&#34; (这就是为什么React应用程序是&#34;应用程序&#34;而不是&#34;网页&#34;)。
React应用程序基于两件事来呈现:
当您使用React时,您明确不所做的是生成HTML元素然后使用它们:例如,当您告诉React使用<input>
时,您就是不创建HTML输入元素,您告诉React创建一个React输入对象,该对象碰巧呈现作为HTML输入元素,并且其事件处理看起来是但不受HTML元素输入事件的控制。
使用React时,您正在做的是生成应用程序UI元素,向用户显示(通常可操作的)数据,用户交互更改组件的状态,可能重新呈现部分应用程序界面以反映新状态。在这个模型中,状态总是最终权限,而不是&#34;无论使用哪个UI库来呈现它&#34;,它在Web上是浏览器的DOM。 DOM在这个编程模型中几乎是一个事后的想法:它只是React碰巧使用的特定UI框架。
因此,对于输入元素,逻辑是:
render
调用,但仅在状态更新更改时 >国家。所有这些都是在几毫秒内发生的,如果不是更少,那么看起来就像你输入元素一样,就像你习惯于&#34;只是在页面上使用输入元素&#34;,但这绝对不是发生的事情。
因此,如上所述,关于如何从React中获取元素的值:
为了正确地执行操作,您的组件具有状态值,该值通过输入字段显示,我们可以通过使该UI元素将更改事件发送回组件来更新它:
var Component = React.createClass({
getInitialState: function() {
return {
inputValue: ''
};
},
render: function() {
return (
//...
<input value={this.state.inputValue} onChange={this.updateInputValue}/>
//...
);
},
updateInputValue: function(evt) {
this.setState({
inputValue: evt.target.value
});
}
});
因此,我们告诉React使用updateInputValue
函数来处理用户交互,使用setState
来安排状态更新,以及render
使用this.state.inputValue
的事实意味着当它在更新状态后重新呈现时,用户将根据他们输入的内容看到更新文本。
基于评论的附录
假设UI输入代表状态值(考虑如果用户中途关闭其标签会发生什么,并且标签已恢复。是否应该恢复所有填充的值?如果是,则表示状态)。这可能会让你觉得大型表单需要几十甚至一百个输入表单,但React是以可维护的方式建模你的UI:你没有100个独立的输入字段,你有相关的输入组,所以你捕获每个组件中的一个组,然后建立你的&#34; master&#34;形成一个群体集合。
MyForm:
render:
<PersonalData/>
<AppPreferences/>
<ThirdParty/>
...
这比单个巨型组件更容易维护。将组拆分为具有状态维护的组件,其中每个组件一次只负责跟踪几个输入字段。
你可能也觉得这很麻烦&#34;麻烦&#34;写出所有代码,但这是一种错误的保存:开发人员 - 包括未来你在内的人 - 实际上从看到所有这些输入明确地获益中获益,因为它使代码路径更容易跟踪。但是,您始终可以进行优化。例如,您可以编写状态链接器
MyComponent = React.createClass({
getInitialState() {
return {
firstName: this.props.firstName || "",
lastName: this.props.lastName || ""
...: ...
...
}
},
componentWillMount() {
Object.keys(this.state).forEach(n => {
let fn = n + 'Changed';
this[fn] = evt => {
let update = {};
update[n] = evt.target.value;
this.setState(update);
});
});
},
render: function() {
return Object.keys(this.state).map(n => {
<input
key={n}
type="text"
value={this.state[n]}
onChange={this[n + 'Changed']}/>
});
}
});
当然,有一些改进的版本,所以点击https://npmjs.com并搜索你最喜欢的React状态链接解决方案。开源主要是关于找到其他人已经完成的事情,并且使用它而不是从头开始编写所有内容。
从React 16开始(以15.5开始软启动),不再支持createClass
调用,需要使用类语法。这改变了两件事:明显的类语法,以及this
可以做的createClass
上下文绑定&#34;免费&#34;,所以为了确保事情仍然有效,请确保你&#39;重新使用&#34;胖箭&#34;在this
处理程序中保留匿名函数的onWhatever
上下文的表示法,例如我们在代码中使用的onChange
:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
inputValue: ''
};
}
render() {
return (
//...
<input value={this.state.inputValue} onChange={evt => this.updateInputValue(evt)}/>
//...
);
},
updateInputValue(evt) {
this.setState({
inputValue: evt.target.value
});
}
});
您可能也看到人们在其构造函数中使用bind
来处理所有事件处理函数,如下所示:
constructor(props) {
super(props);
this.handler = this.handler.bind(this);
...
}
render() {
return (
...
<element onclick={this.handler}/>
...
);
}
不要这样做。
几乎在您使用bind
的任何时候,谚语&#34;您做错了&#34;适用。您的类已经定义了原型,因此编程模型已经定义了实例上下文。不要将bind
放在使用普通事件转发的顶部,而不是在构造函数中复制所有函数调用。现在,您已经增加了错误表面,并且更难以跟踪错误,因为问题可能出在构造函数中,而不是您调用代码的位置。除了对您(拥有或选择)使用的其他人施加维护负担之外。
是的,我知道反应文件说它很好。它没有,不做。
从React 16.8开始,函数组件(即字面上只是一个以props
为参数的函数可以用作组件类的实例,而不用编写类)也可以通过使用hooks来获得国家。
如果您不需要完整的类代码,并且单个实例函数可以执行,那么您现在可以使用useState
挂钩来获取单个状态变量及其更新功能,与上述示例大致相同,但没有setState
函数调用:
import { useState } from 'react';
function myFunctionalComponentFunction() {
const [input, setInput] = useState(''); // '' is the initial state value
return (
<div>
<label>Please specify:</label>
<input value={input} onInput={e => setInput(e.target.value)}/>
</div>
);
}
以前,类和功能组件之间的非官方区别是&#34;功能组件没有状态&#34;,所以我们不能再隐藏在那个组件之后:功能组件和类之间的区别可以在写得很好的react documentation中找到分布在几页上的组件(没有快捷方便的说明,以方便你误解!),你应该阅读这些内容,这样你才能知道自己在做什么,从而可以知道你是否选择了最好的(对你来说意味着什么)解决方案,让你自己摆脱你遇到的问题。
答案 1 :(得分:11)
通过执行以下操作来管理获取输入字段值:
import React, { Component } from 'react';
class App extends Component {
constructor(props){
super(props);
this.state = {
username : ''
}
this.updateInput = this.updateInput.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
updateInput(event){
this.setState({username : event.target.value})
}
handleSubmit(){
console.log('Your input value is: ' + this.state.username)
//Send state to the server code
}
render(){
return (
<div>
<input type="text" onChange={this.updateInput}></input>
<input type="submit" onClick={this.handleSubmit} ></input>
</div>
);
}
}
//output
//Your input value is: x
答案 2 :(得分:7)
在反应16中,我使用
<Input id="number"
type="time"
onChange={(evt) => { console.log(evt.target.value); }} />
答案 3 :(得分:4)
给<input>
一个唯一的ID
<input id='title' ...>
,然后使用standard Web API在DOM中引用它
const title = document.getElementById('title').value
无需每次按键都不断更新React状态。只需在需要时获取值即可。
答案 4 :(得分:3)
我通过绑定&#34;这个&#34;成功地做到了这一点。到功能 updateInputValue(evt)with
this.updateInputValue = this.updateInputValue.bind(this);
但输入值= {this.state.inputValue} ... 结果证明不是个好主意。
这是babel ES6中的完整代码:
class InputField extends React.Component{
constructor(props){
super(props);
//this.state={inputfield: "no value"};
this.handleClick = this.handleClick.bind(this);
this.updateInputValue = this.updateInputValue.bind(this);
}
handleClick(){
console.log("trying to add picture url");
console.log("value of input field : "+this.state.inputfield);
}
updateInputValue(evt){
//console.log("input field updated with "+evt.target.value);
this.state={inputfield: evt.target.value};
}
render(){
var r;
r=<div><input type="text" id="addpixinputfield"
onChange={this.updateInputValue} />
<input type="button" value="add" id="addpix" onClick={this.handleClick}/>
</div>;
return r;
}
}
答案 5 :(得分:2)
你的错误是因为你使用了类,当使用类时我们需要将函数绑定到This以便正常工作。无论如何,有很多教程为什么我们应该“这个”以及javascript中的“this”做什么。
如果您更正了提交按钮,则应该可以正常工作:
<button type="button" onClick={this.onSubmit.bind(this)} className="btn">Save</button>
如果你想在控制台中显示该输入的值,你应该使用var title = this.title.value;
答案 6 :(得分:1)
返回一个有状态的值,以及一个更新它的函数。
在初始渲染期间,返回的状态 (state)
与作为第一个参数 (initialState)
传递的值相同。
setState
函数用于更新状态。它接受一个新的状态值并将组件的重新渲染排入队列。
源 ---> https://reactjs.org/docs/hooks-reference.html#usestate
useRef
返回一个可变引用对象,其 .current
属性被初始化为传递的参数 (initialValue)
。返回的对象将在组件的整个生命周期内持续存在。
源 ---> https://reactjs.org/docs/hooks-reference.html#useref
import { useRef, useState } from "react";
export default function App() {
const [val, setVal] = useState('');
const inputRef = useRef();
const submitHandler = (e) => {
e.preventDefault();
setVal(inputRef.current.value);
}
return (
<div className="App">
<form onSubmit={submitHandler}>
<input ref={inputRef} />
<button type="submit">Submit</button>
</form>
<p>Submit Value: <b>{val}</b></p>
</div>
);
}
答案 7 :(得分:1)
在函数组件中:-
export default function App(){
const [state, setState] = useState({
value:'',
show:''
});
const handleChange = (e) => {
setState({value: e.target.value})
}
const submit = () => {
setState({show: state.value})
}
return(
<>
<form onSubmit={()=>submit()}>
<input type="text" value={state.value} onChange={(e)=>handleChange(e)} />
<input type="submit" />
</form>
<h2>{state.show}</h2>
</>
)}
答案 8 :(得分:1)
export default class App extends React.Component{
state={
value:'',
show:''
}
handleChange=(e)=>{
this.setState({value:e.target.value})
}
submit=()=>{
this.setState({show:this.state.value})
}
render(){
return(
<>
<form onSubmit={this.submit}>
<input type="text" value={this.state.value} onChange={this.handleChange} />
<input type="submit" />
</form>
<h2>{this.state.show}</h2>
</>
)
}
}
答案 9 :(得分:1)
最简单的方法是使用箭头功能
您的带有箭头功能的代码
export default class MyComponent extends React.Component {
onSubmit = (e) => {
e.preventDefault();
var title = this.title;
console.log(title);
}
render(){
return (
...
<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">Save</button>
...
);
}
};
答案 10 :(得分:0)
export default class MyComponent extends React.Component {
onSubmit(e) {
e.preventDefault();
var title = this.title.value; //added .value
console.log(title);
}
render(){
return (
...
<form className="form-horizontal">
...
<input type="text" className="form-control" ref={input => this.title = input} name="title" />
...
</form>
...
<button type="button" onClick={this.onSubmit} className="btn">Save</button>
...
);
}
};
答案 11 :(得分:0)
如果您使用类组件,则只需3个步骤-首先,您需要声明输入字段的状态,例如 this.state = {name:''} 。其次,您需要编写一个用于在以下示例中更改状态时设置状态的函数,例如 setName(),最后您必须编写输入jsx,例如
import React, { Component } from 'react'
export class InputComponents extends Component {
constructor(props) {
super(props)
this.state = {
name:'',
agree:false
}
this.setName = this.setName.bind(this);
this.setAgree=this.setAgree.bind(this);
}
setName(e){
e.preventDefault();
console.log(e.target.value);
this.setState({
name:e.target.value
})
}
setAgree(){
this.setState({
agree: !this.state.agree
}, function (){
console.log(this.state.agree);
})
}
render() {
return (
<div>
<input type="checkbox" checked={this.state.agree} onChange={this.setAgree}></input>
< input value={this.state.name} onChange = {this.setName}/>
</div>
)
}
}
export default InputComponents
答案 12 :(得分:0)
使用不受控制的字段:
export default class MyComponent extends React.Component {
onSubmit(e) {
e.preventDefault();
console.log(e.target.neededField.value);
}
render(){
return (
...
<form onSubmit={this.onSubmit} className="form-horizontal">
...
<input type="text" name="neededField" className="form-control" ref={(c) => this.title = c} name="title" />
...
</form>
...
<button type="button" className="btn">Save</button>
...
);
}
};
答案 13 :(得分:0)
将您的参考更改为:ref='title'
并删除name='title'
然后删除var title = this.title
并输入:
console.log(this.refs.title.value)
另外,您应将.bind(this)
添加到this.onSubmit
(在我的情况下,它的工作原理非常相似,但不是onClick
,而是onSubmit={...}
,它以(<form onSubmit={...} ></form>)
的形式出现)
答案 14 :(得分:0)
// On the state
constructor() {
this.state = {
email: ''
}
}
// Input view ( always check if property is available in state {this.state.email ? this.state.email : ''}
<Input
value={this.state.email ? this.state.email : ''}
onChange={event => this.setState({ email: event.target.value)}
type="text"
name="emailAddress"
placeholder="johdoe@somewhere.com" />
答案 15 :(得分:0)
您应该在MyComponent类下使用构造函数扩展React.Component
constructor(props){
super(props);
this.onSubmit = this.onSubmit.bind(this);
}
然后您将获得标题的结果
答案 16 :(得分:0)
您可以在不添加“onChange”功能的情况下获取输入值。
只需在输入元素中添加'ref attr:
即可
然后使用this.refs在需要时获取输入值。