2017-04-30 84 views
3

我試圖用react/redux去除textarea的值,並在div#preview中顯示去抖值,但是我在第一次函數調用後收到合成事件警告。debounce textarea input with react/redux

我有處理textarea值狀態的減速器,它按照預期工作,但爲了簡單起見,我在這段代碼中寫了本地狀態。

如果除了debounce之外還有更好的方法來避免在每個keypress之後發生反應,我很想知道。提前致謝。

class TextArea extends React.Component { 
 
    constructor(props){ 
 
    super(props); 
 
    this.state = {foo: ''} 
 
    } 
 
    
 
    handleInputChange = _.debounce((e) => { 
 
    e.persist(); 
 
    let value = e.target.value; 
 
    this.setState({foo: value}); 
 
    }, 300); 
 

 
    render() { 
 
    return (
 
     <div> 
 
     <textarea onChange={(e)=>this.handleInputChange(e)} value={this.state.foo}></textarea> 
 
     <p id="preview">{this.state.foo}</p> 
 
     </div> 
 
    ); 
 
    } 
 
} 
 

 

 
ReactDOM.render(
 
    <TextArea />, 
 
    document.getElementById("react") 
 
);
<div id="react"></div> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

+0

您的價值是基於狀態,但只是以去抖方式更新......這是否適合您?你爲什麼需要去抖? –

+0

如上所述,我有一個'預覽div',如果在'textarea'中有一個長按鍵或者100個以上的字符,由於不斷重新渲染,反應開始變得遲緩。是的,在給定的防反跳時間警告顯示之後,防抖動僅工作一次。對無效值做出反應警告:'由於性能原因,此綜合事件被重用。如果您看到這一點,那麼您正在訪問已發佈/無效合成事件的屬性目標。這被設置爲空。如果你必須保持原來的合成事件,使用event.persist()。' – nehel

+0

我在處理redux週期時遇到了延遲。關於組件的本地狀態,我還沒有看到這種情況發生..你能在小提琴中重現嗎? –

回答

1

,因爲你嘗試.persist()debounce的超時內事件中,你得到這個錯誤。當超時調用回調時,合成事件已經釋放。所以你必須堅持事件以外的反彈。

但是,您的想法有另一個問題。由於文本框是一個受控組件,因此如果刪除更新後的值,將導致文本框僅在使用停止鍵入之後才呈現(部分文本)文本。

爲了防止您需要立即更新受控元素的狀態併爲顯示狀態(或redux操作分派)消除更新。

例如:

class TextArea extends React.Component { 
 
    constructor(props){ 
 
    super(props); 
 
    this.state = { foo: '', controlled: '' } 
 
    } 
 
    
 
    updateFoo = _.debounce((value) => { // this can also dispatch a redux action 
 
    this.setState({foo: value}); 
 
    }, 300); 
 
    
 
    handleInputChange = (e) => { 
 
    const value = e.target.value; 
 
    
 
    this.setState({ 
 
     controlled: value 
 
    }); 
 
    
 
    this.updateFoo(value); 
 
    } 
 

 
    render() { 
 
    return (
 
     <div> 
 
     <textarea onChange={ this.handleInputChange } 
 
     value={this.state.controlled} /> 
 
     <p id="preview">{this.state.foo}</p> 
 
     </div> 
 
    ); 
 
    } 
 
} 
 

 

 
ReactDOM.render(
 
    <TextArea />, 
 
    document.getElementById("react") 
 
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 
<div id="react"></div>

+0

哦,我明白了魔法從哪裏來。雖然,由於第二個狀態爲「受控」,這是否意味着我必須將第二個狀態添加到用於更新textarea值或單獨的reducer的reducer中?除非我必須在本地設置'controlled'狀態。 – nehel

+0

您可以在本地設置'受控'狀態,因爲只需要更新'debta'中的'textarea',您將派發更新存儲的操作。 –

0

對方回答已經與持續的事件所涉及的問題。對於輸入消除方面,您可能需要閱讀我的博文Practical Redux, Part 7: Form Change Handling。在那篇文章中,我展示了一個可重用組件,它可以處理應用程序其餘部分的文本輸入更新消除,同時允許它們立即使用當前值重新呈現。