键入时ReactJS延迟onChange

chr*_*ris 6 javascript reactjs

我需要更改状态以维护用户键入的字符串。但是我想延迟一个操作,直到用户停止键入为止。但是我不能完全专注于如何做到这两者。

因此,当用户停止键入时,我希望触发一个动作,而不是之前。有什么建议么?

小智 50

使用 React Hooks 和 Function 组件

要保留用户正在键入的字符串,请使用useState钩子来存储用户正在键入的文本。然后将该状态赋予输入的值。还要确保在输入setStateonChange事件处理程序上使用,否则输入值不会改变。

要仅在用户停止输入后的某个时间触发操作,您可以将useEffect钩子与setTimeout. 在这种情况下,我们希望useEffect在输入值更改时触发,因此我们将创建一个useEffect钩子并在其依赖数组上为其提供具有输入值的变量。给定的函数useEffect应该用于setTimeout在所需的延迟时间后触发操作。此外,给定的函数useEffect应该返回一个清除超时设置的清理函数。这避免了对不再与用户相关的输入值执行操作。

下面是一个应用程序的小例子,它使用上述步骤来保持用户输入的字符串可见,并在用户停止输入 500 毫秒后显示完成的字符串。

function App() {
  const [query, setQuery] = useState("");
  const [displayMessage, setDisplayMessage] = useState("");

  useEffect(() => {
    const timeOutId = setTimeout(() => setDisplayMessage(query), 500);
    return () => clearTimeout(timeOutId);
  }, [query]);

  return (
    <>
      <input
        type="text"
        value={query}
        onChange={event => setQuery(event.target.value)}
      />
      <p>{displayMessage}</p>
    </>
  );
}
Run Code Online (Sandbox Code Playgroud)

  • 上面的想法很好,尽管我会使用库 debounce 函数,而不是 setTimeout,例如使用 Lodash:https://lodash.com/docs/#debounce (5认同)

Cha*_*nda 22

setTimeout一旦用户输入文本,您将需要使用这些声音来启动计时器。如果用户输入另一个字符,则重新启动计时器。如果用户在计时器完成之前没有再次输入,它将触发一个切换复选框的动作:

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      text: '',
      checked: false
    };
    this.timer = null;
  }
  
  componentDidUpdate (prevProps, prevState) {
    if(prevState.text !== this.state.text) {
      this.handleCheck();
    }
  }
  
  onChange = e => {
    this.setState({
      text: e.target.value
    });
  };
  
  handleCheck = () => {
    // Clears running timer and starts a new one each time the user types
    clearTimeout(this.timer);
    this.timer = setTimeout(() => {
      this.toggleCheck();
    }, 1000);
  }
  
  toggleCheck = () => {
    this.setState( prevState => ({ checked: !prevState.checked }));
  }
  
  render () {
    return (
      <div>
        <input value={this.state.text} onChange={this.onChange} placeholder="Start typing..." /><br/>
        <label>
          <input type="checkbox" checked={this.state.checked} onChange={this.toggleCheck} />
          Toggle checkbox after user stops typing for 1 second
        </label>
      </div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
Run Code Online (Sandbox Code Playgroud)
<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="root"></div>
Run Code Online (Sandbox Code Playgroud)


ric*_*ges 17

一种方法是让您的onChange处理程序执行两个函数:

  • 立即更新状态的函数
  • 去抖函数

示例代码:

import debounce from 'lodash.debounce';

class Foo extends React.Component {
  constructor() {
    super()

    this.state = {
      value: ''
    }

    // Delay action 2 seconds
    this.onChangeDebounced = debounce(this.onChangeDebounced, 2000)
  }

  handleInputChange = (e: Event) => {
    // Immediately update the state
    this.setState({
      value: e.target.value
    })

    // Execute the debounced onChange method
    this.onChangeDebounced(e)
  }

  onChangeDebounced = (e: Event) => {
    // Delayed logic goes here
  }

  render() {
    return (
      <input onChange={this.handleInputChange} value={this.state.value} />
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案。我首先尝试了上面的答案,但它调用了文本更改的逻辑时间数。就我而言,我在更改事件时调用 api,因此我想在用户输入文本后调用它,而不是在每次更改时调用 api。您的答案就是完美的解决方案。谢谢 (3认同)

小智 9

使用 React Hooks - useRef

const timer = useRef(null)
    
useEffect(() => {
    
    clearTimeout(timer.current)
    timer.current = setTimeout(() => {
     // your logic
    },1000)
    
},[value])
Run Code Online (Sandbox Code Playgroud)


小智 6

使用 React Hooks 和 Function 组件

const [timer, setTimer] = useState(null);

function changeDelay(change) {
    if (timer) {
      clearTimeout(timer);
      setTimer(null);
    }
    setTimer(
      setTimeout(() => {
        console.log(change);
      }, 3000)
    );
}
Run Code Online (Sandbox Code Playgroud)

在输入

<input type="text" onChange={(e) => { changeDelay(e.target.value); }} />
Run Code Online (Sandbox Code Playgroud)