我正在尝试通过实现Thinking in React来试验reactjs多字段组件,但无法弄清楚为什么这里的子方法被多次调用。
var i = 0;
class SearchBar extends Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange(key) {
//this method is called multiple times during Render()
console.log(i++);
return function(e) {
var value = key !== 'inStockOnly' ? e.target.value : e.target.checked;
this.props.onUserInput(
key,
value
);
}.bind(this);
}
render() {
return (
<form>
<input type="search" value={this.props.filterText} placeholder="Search ..." ref={(input) => {input.focus();}} onChange={this.handleChange('filterText')} />
<p>
<input type="checkbox" checked={this.props.inStockOnly} onChange={this.handleChange('inStockOnly')} />
{' '}
Only show products in stock
</p>
</form>
);
}
}
class FilterableProducts extends Component {
constructor(props) {
super(props);
this.state = {
filterText: '',
inStockOnly: false
};
this.handleInput = this.handleInput.bind(this);
}
handleInput(key, value) {
/*var state = {};
state[key] = value;
console.log(state);
this.setState(state);*/
//above is what I am trying to do later on but still stuck on why setState does not work
//test
this.setState({
filterText: 'foo',
inStockOnly: true
});
}
render() {
return (
<SearchBar filterText={this.state.filterText} inStockOnly={this.state.inStockOnly} onUserInput={this.handleInput} />
);
}
}
&#13;
//updated handleChanged
handleChange(key, e) {
var value = key !== 'inStockOnly' ? e.target.value : e.target.checked;
this.props.onUserInput(
key,
value
);
}
//updated handleInput
handleInput(key, value) {
//var state = {};
//state[key] = value;
//this.setState(state);
//console.log(state);
//above is what I am trying to do
//test
this.setState({
filterText: 'g',
inStockOnly: true
});
}
&#13;
<!--i changed the event listener to this
now its not called directly
-->
<input type="search" value={this.props.filterText} placeholder="Search ..." ref={(input) => {input.focus();}} onChange={(e)=>this.handleChange('filterText', e)} />
&#13;
任何建议表示赞赏
答案 0 :(得分:1)
编辑:这是正确的,它们应该立即被调用,因为你正在返回一个与onChange
绑定的函数。内部函数只会被称为onChange
。您需要传递密钥。
第二次修改:
handleInput(event) {
this.setState({
filterText: event.target.value,
inStockOnly: true
});
}
<input type="search" value={this.state.filterText} placeholder="Search ..." ref={(input) => {input.focus();}} onChange={this.handleInput} />
原创:
handleChange(key) {
//this method is called multiple times during Render()
console.log(i++);
return function(key, event) {
var value = key !== 'inStockOnly' ? event.target.value : event.target.checked;
this.props.onUserInput(
key,
value
);
}.bind(this);
}
事件将在触发时作为最后一个参数传递。
setState
什么不起作用?您在handleInput
中正确使用它。
注释掉的setState
不会起作用。您应该只在构造函数中创建状态,并且还要注意,设置状态后console.log()
可能仍然是空的,因为setState
对于性能是异步的,并且可能直到稍后才更新。
var state = {};
state[key] = value;
console.log(state);
this.setState(state);*/
您需要componentDidUpdate
代替并在其中执行console.log或使用setState
的回调,即this.setState({state[key]: value}, function() {console.log(this.state)});
,它将始终提供正确的状态。
答案 1 :(得分:0)
刚刚发现为什么我的'setState'“不工作”。这是因为没有正确使用ref
属性。通过删除ref={(input) => {input.focus();}}
,代码将起作用。在我的情况下,我可以将其更改为ref={(input) => if(input === null) return; {input.focus();}}
将保持焦点功能。这是因为ref
函数被调用两次:whenMount
和didMount
如此全功能的方法将是:
class SearchBar extends Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange(key, e) {
var value = key !== 'inStockOnly' ? e.target.value : e.target.checked;
this.props.onUserInput(
key,
value
);
}
render() {
return (
<form>
<input type="search" value={this.props.filterText} placeholder="Search ..." ref={(input) => {if(input === null) return;input.focus();}} onChange={(e)=>this.handleChange('filterText', e)} />
<p>
<input type="checkbox" checked={this.props.inStockOnly} onChange={(e)=>this.handleChange('inStockOnly', e)} />
{' '}
Only show products in stock
</p>
</form>
);
}
}
class FilterableProducts extends Component {
constructor(props) {
super(props);
this.state = {
filterText: '',
inStockOnly: false
};
this.handleInput = this.handleInput.bind(this);
}
handleInput(key, value) {
var state = {};
state[key] = value;
this.setState(state);
}
render() {
return (
<SearchBar filterText={this.state.filterText} inStockOnly={this.state.inStockOnly} onUserInput={this.handleInput} />
);
}
}
使用onChange={(e)=>this.handleChange('inStockOnly', e)} />
和onChange={(e)=>this.handleChange('filterText', e)}
我们可以避免在多个字段中使用很多ref
组件