web-dev-qa-db-ja.com

作る方法React onChange Set State]を設定した後にのみ、設定時間の間に停止した後にのみ入力onchange set stateは?

イントロCreate-React-Appアプリにユーザー入力要素を持っています。ユーザーは数字を入力するか、矢印を使用して数を上下に増やすことができます。出力はこの番号を表示します。

enter image description here

問題ユーザーは特定の数字に到着したい、そしてそれらが数に入力されていても、onchange eventListenerをトリガーするスプリアス中間値があります。ユーザーがキーボードで「15」と入力しようとした場合、出力は最初の "1"、次に "15"ですが、「15」になるだけです。ボタン/送信/ etcまたはその他のイベントを使用したくはありません。ユーザーが0から500の上向き矢印を押して保持している場合は、「高速な変更」入力が遅くなった後、500に直接アップデートしたいと思います。

目標OnChange関数をプログラムして、OnChangeが更新されるようにNOTの場合にのみ更新されるようにします。最後のイベント以降に少なくとも600ミリ秒間イベントを発行しました。

詳細ユーザーが '1'を入力し、次に '5'( '15'の場合)が600ms未満の場合、出力は '15'に更新されるはずですそして '1'をスキップします。ただし、「1」と「5」の入力の間でユーザーが600msを超える場合、出力は最初に '1'、次に '5'になります。同様に、ユーザーが増分矢印を非常に高速かつダウンダウンしている場合、出力は停止または遅くまで更新しないでください。

ターミナルで、CREATE-REACT-APPを使用してReactアプリを作成します。

create-react-app delay-output-app

 _

コードこれを遅延output-app/src/app.jsにコピーして貼り付けて、以前のコードをすべて置き換えます。

import React, { useState, useEffect, useRef } from "react";
import "./App.css";

function App() {
  const inputRef = useRef();
  const [userValue, setUserValue] = useState(0);
  const [output, setOutput] = useState(0);

  const updateOutput = () => {
    setUserValue(inputRef.current.value);
    setOutput(inputRef.current.value);
    //if input is changing quickly - do not update output
    //only update output if input has not changed for 700ms since last change.
  };

  return (
    <div className="App">
      <br></br>
      <div>
        <h1>Input</h1>
        <input
          ref={inputRef}
          value={userValue}
          type="number"
          onChange={updateOutput}
        ></input>
      </div>
      <br></br>
      <div>
        <h1>Output</h1>
        {output}
      </div>
    </div>
  );
}

export default App;

 _

端末のアプリを実行するには...

cd delay-output-app
npm start
 _

私はSetTimeoutとSetIntervalで遊んで遊んでみましたが、特にReact UseEffectフックと組み合わせると問題に遭遇し続けます。繰り返しますが、ボタンを使用したり、ユーザーを入力したり、矢印をクリックして出力を更新したりする必要があります。入力値の間の時間だけが入力値が中間のとき、または出力を更新する必要があるときだけです。

Debounceを含めるの更新 - 私は、入力イベントが終了するまでデバウンスが実行されるべき印象の下にありますが、まだ更新出力を取得していますユーザー入力イベントが終了した場合に関係なく、待機期間の後。

ロダッシュデバウンスのコード

import React, { useState, useRef } from "react";
import "./App.css";
import _ from "lodash";

function App() {
  const inputRef = useRef();
  const [userValue, setUserValue] = useState(0);
  const [output, setOutput] = useState(0);

  const updateOutput = _.debounce(
    () => setOutput(inputRef.current.value),
    700
  );
  //if input is changing quickly - do not update output
  //only update output if input has not changed for 700ms since last change.

  const updateUserValue = () => {
    setUserValue(inputRef.current.value);
  };
  return (
    <div className="App">
      <br></br>
      <div>
        <h1>Input</h1>
        <input
          ref={inputRef}
          value={userValue}
          type="number"
          onChange={() => {
            updateOutput();
            updateUserValue();
          }}
        ></input>
      </div>
      <br></br>
      <div>
        <h1>Output</h1>
        {output}
      </div>
    </div>
  );
}

export default App;


 _
6
NicoWheat

これを解決するには本当にREFが必要ありません。 useEffectへの呼び出しで十分なはずです。

useEffect(() => {
  const timeout = setTimeout(() => {
    setOutput(userValue);
  }, 600);
  return () => {
    clearTimeout(timeout);
  };
}, [userValue]);

const updateOutput = (e) => {
  setUserValue(e.target.value);
};
 _
1
Damien Flury