2017-04-30 14 views
3

私はreact/reduxでテキストエリアの値をデバウンスして、デバッグされた値をdiv#previewに表示しようとしていますが、最初の関数呼び出し後に合成イベントの警告が表示されます。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+文字のように、反応は絶え間なく再レンダリングされて地獄のように遅くなり始めます。そして、はい、デバウンスの警告が表示された後、デバウンスは1回だけ動作します。無効化された値に対して警告を出します: 'この合成イベントは、パフォーマンス上の理由から再利用されます。これが表示されている場合は、公開/無効化された合成イベントでプロパティターゲットにアクセスしています。これはnullに設定されます。元の合成イベントを回避する必要がある場合は、event.persist()を使用してください。 ' – nehel

+0

reduxサイクルを処理するときに、ラグが発生しました。コンポーネントのローカル状態では、私はこれが起こっているのを見たことがありません。あなたはフィドルで再現できますか? –

答えて

1

あなたはdebounceのタイムアウト内.persist()にイベントを試みるため、このエラーが発生します。タイムアウトがコールバックを呼び出すと、合成イベントはすでに解放されました。だから、あなたはデバウンスの外でイベントを持続させなければならないでしょう。

しかし、あなたのアイデアには別の問題があります。テキストボックスは制御されたコンポーネントであるため、更新された値をデバウンスすると、テキストボックスは、使用されていない入力の後にのみテキストの一部をレンダリングします。

制御された要素の状態を直ちに更新し、表示状態(または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

ああ、今からどこから魔法が出るのか分かります。しかし、第2の状態が「制御されている」ということは、テキスト領域の値を更新するか、別の減速機を更新するための減速機に第2の状態を追加する必要があるということですか?私は制御された状態をローカルに設定しなければならない。 – nehel

+0

あなたは 'textarea'を更新するだけで' controlled'状態を設定することができます。 'debounce'ではストアを更新するアクションをディスパッチします。 –

0

他の答えは、すでにイベントを永続化の問題をカバーしました。入力のデバウンスの面については、私のブログ投稿Practical Redux, Part 7: Form Change Handlingを読んでみてください。その記事では、残りのアプリケーションのデバウンステキスト入力の更新を処理できる再利用可能なコンポーネントを示し、同時に現在の値で再レンダリングできるようにしています。

関連する問題