因此,我正在尝试学习与Rails一起反应(仅将Rails用作API)。我制作了一个简单的待办事项应用程序,尝试“创建”列表时陷入困境。
我在这里显示了一个“新列表”组件,该组件主要来自于React Forms教程:
import React, { Component } from 'react';
import axios from 'axios';
class ListForm extends Component {
constructor(props) {
super(props);
this.state = {
title: '',
description: ''
};
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
this.setState({[e.target.name]: e.target.value});
}
handleSubmit(e) {
console.log("Form submitted with: " + this.state.value)
e.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Title:
<input name="title" type="text" value={this.state.value} onChange={this.handleInputChange} />
</label>
<label>
Description:
<textarea name="description" value={this.state.value} onChange={this.handleInputChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
export default ListForm;
我的ListContainer显示在这里
import React, { Component } from 'react';
import axios from 'axios';
import List from './List';
import ListForm from './ListForm'
class ListContainer extends Component {
constructor(props){
super(props)
this.state = {
lists: []
}
this.addNewList = this.addNewList.bind(this)
}
componentDidMount() {
axios.get('/api/v1/lists.json')
.then(response => {
console.log(response)
this.setState({
lists: response.data
})
})
.catch(error => console.log(error))
}
addNewList(title, description) {
axios.post('/api/v1/lists.json', {
title: title,
description: description
})
.then(function (response) {
console.log(response);
const lists = [ ...this.state.lists, response.data ]
console.log(...this.state.lists)
this.setState({lists})
})
.catch(function (error) {
console.log(error);
});
}
render() {
return (
<div className="lists-container">
{this.state.lists.map( list => {
return (<List list={list} key={list.id} />)
})}
<ListForm onSubmit={this.addNewList} />
</div>
)
}
}
export default ListContainer;
我的问题来自对提交回调的误解。我知道当我在表单上执行“ onSubmit”时,它使用addNewList函数作为回调....但是我真的不明白,ListForm中的状态连接如何进入该回调函数。我显然在做错事,因为它不起作用,并且当前控制台显示“ Form with with:undefined”,因此它根本无法正确传递参数。
我对React还是很陌生的,并且对JS非常生锈(自从我使用它以来,已经有点了,所以我确定这里有一些新手错误)。同样,axios基本上是一种“更好的”获取方式。
我也不会说谎,我也不完全理解为什么我们要this.handleSubmit = this.handleSubmit.bind(this);
(以及其他类似的事情)
答案 0 :(得分:1)
我想你也有错字。对于变更事件,您有
<input name="title" type="text" value={this.state.value} onChange={this.handleInputChange} />
因此,更改的回调为this.handleInputChange
。但是在您的代码中,其名为handleChange
但是,即使您使用了正确的命名,它也不起作用,因为您还需要绑定该函数。
这使我想到了关于this.handleSubmit = this.handleSubmit.bind(this);
这里的问题是,当您将函数作为回调传递时,它将丢失其上下文。考虑以下
const x = {
log: function() { console.log(this.val) },
val: 10
}
现在您可以做
x.log(); // -> print 10
但是当你这样做
y = x.log;
y(); // -> prints undefined
如果仅传递周围的函数,则会失去其上下文。要解决此问题,您可以bind
x.log = x.log.bind(x);
y = x.log
y(); // -> prints 10
希望这很有意义:)
无论如何,回到您的问题上,您不必使用绑定,有更好的方法
class ListForm extends Component {
constructor(props) {
super(props);
this.state = {
title: '',
description: ''
};
}
handleChange = (e) => {
this.setState({[e.target.name]: e.target.value});
}
handleSubmit = (e) => {
console.log("Form submitted with: " + this.state.value)
e.preventDefault();
}
虽然没有经过测试,但现在可能会正常工作!
答案 1 :(得分:1)
您是如此亲密!我们只需要进行一些调整。
首先让我们丢失bind语句,仅使用箭头函数。箭头函数没有this
对象,因此,如果在该函数内调用this
,则实际上将访问类实例的this
对象。整洁。
第二,让我们修复handleChange函数上的错字,以便您的输入正确更新组件状态。
现在,真正解决您的问题。您需要在父组件ListContainer中调用addNewList函数。我们该怎么做?让它作为道具传递给子组件!您快到了,但是不要使用关键字onSubmit={this.addNewList}
,而要使用类似handleSubmit
的名称。这是因为onSubmit实际上是一个特殊的关键字,它将事件侦听器附加到要提交的子组件上,而我们不希望这样做。
现在,您的子组件正在充当道具。我们可以在handleSubmit函数中调用它。然后,我们传入参数,标题和描述。现在,您的子组件可以在父组件中调用addNewList函数!
import React, { Component } from 'react';
import axios from 'axios';
import List from './List';
import ListForm from './ListForm'
class ListContainer extends Component {
constructor(props) {
super(props)
this.state = {
lists: []
}
this.addNewList = this.addNewList.bind(this)
}
componentDidMount() {
axios.get('/api/v1/lists.json')
.then(response => {
console.log(response)
this.setState({
lists: response.data
})
})
.catch(error => console.log(error))
}
addNewList(title, description) {
axios.post('/api/v1/lists.json', {
title: title,
description: description
})
.then(function (response) {
console.log(response);
const lists = [...this.state.lists, response.data]
console.log(...this.state.lists)
this.setState({ lists })
})
.catch(function (error) {
console.log(error);
});
}
render() {
return (
<div className="lists-container">
{this.state.lists.map(list => {
return (<List list={list} key={list.id} />)
})}
<ListForm handleSubmit={this.addNewList} />
</div>
)
}
}
export default ListContainer;
import React, { Component } from 'react';
import axios from 'axios';
class ListForm extends Component {
constructor(props) {
super(props);
this.state = {
title: '',
description: ''
};
}
handleChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
}
handleSubmit = (e) => {
this.props.handleSubmit(this.state.title, this.state.description);
e.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Title:
<input name="title" type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<label>
Description:
<textarea name="description" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
答案 2 :(得分:0)
使用this.state.title
和this.state.description
更改输入的值属性:
<input name="title" type="text" value={this.state.title} onChange={this.handleInputChange} />
<textarea name="description" value={this.state.description} onChange={this.handleInputChange} />
尝试使用
打印信息console.log("Form submitted with: ", this.state)
关于.bind(this)
:
this
指向已调用的事件。.bind(this)
箭头功能外,它还用于this
。但是对于长层次结构而言,这不是可取的。