2016-12-24 75 views
0

我試圖通過實現Thinking in React來試驗reactjs多個字段組件,但無法找出爲什麼在這裏調用多次的子方法。防止在React JS中多次調用方法

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} />    
 
    ); 
 
    } 
 
}
更新:

//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 
 
    }); 
 
}
<!--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)} />

任何意見讚賞的

+0

請參閱我的編輯。你的功能也應該被調用。它只會在輸入變爲現在而不是渲染時調用。 –

回答

1

編輯:這是心病rect,他們應該立即被調用,因爲你正在返回一個綁定到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)});它總會給正確的狀態。

+0

非常感謝你,這是回答這個問題。但我仍然無法使我的setState作品。最後嘗試當我刪除'返回功能()..''handleInput()'沒有得到調用 – RizkiDPrast

+0

@RizkiDPrast你在談論'handleInput'或'handleChange'函數?我不懂你在說什麼。 –

+0

@RizkiDPrast實際上從'handleChange'返回函數應該仍然有效,但是內部函數只會被調用'onChange',所以你所做的是正確的,函數會被立即調用,因爲它們會返回一個被綁定的函數到'onChange' –

0

剛剛發現爲什麼我的'setState'「不工作」。這是因爲ref屬性的使用不當。通過刪除ref={(input) => {input.focus();}},代碼將起作用。而在我的情況下,我可以將其更改爲ref={(input) => if(input === null) return; {input.focus();}}將保持對焦功能。這是因爲ref函數被調用兩次:whenMountdidMount

如此全功能的方法是:

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字段組件