116 votes

Comment utiliser l'accélérateur ou le ralentisseur avec React Hook ?

J'essaie d'utiliser le throttle méthode de lodash dans un composant fonctionnel, par exemple :

const App = () => {
  const [value, setValue] = useState(0)
  useEffect(throttle(() => console.log(value), 1000), [value])
  return (
    <button onClick={() => setValue(value + 1)}>{value}</button>
  )
}

Puisque la méthode dans useEffect est redéclarée à chaque rendu, l'effet d'étranglement ne fonctionne pas.

Quelqu'un a-t-il une solution simple ?

1 votes

Est-ce une option pour vous de définir la fonction étranglée en dehors de la App et l'appeler simplement dans le composant useEffect fonction ?

0 votes

Oui, j'ai essayé et cela fonctionne, mais dans mon cas, ce n'est pas très élégant, car j'utilise des variables de composants dans la méthode d'étranglement.

7voto

Saman Mohamadi Points 1384

J'ai écrit deux crochets simples ( effet d'étranglement y utilisation de l'effet rebond ) pour ce cas d'utilisation, il sera peut-être utile à quelqu'un d'autre qui cherche une solution simple.

import React, { useState } from 'react';
import useThrottledEffect  from 'use-throttled-effect';

export default function Input() {
  const [count, setCount] = useState(0);

  useEffect(()=>{
    const interval = setInterval(() => setCount(count=>count+1) ,100);
    return ()=>clearInterval(interval);
  },[])

  useThrottledEffect(()=>{
    console.log(count);     
  }, 1000 ,[count]);

  return (
    {count}
  );
}

0 votes

A fonctionné parfaitement, merci. J'ai testé les deux crochets

4voto

gazdagergo Points 993

Je voudrais me joindre à la fête avec mon entrée étranglée et débitée en utilisant useState :

// import { useState, useRef } from 'react' // nomral import
const { useState, useRef } = React // inline import

// Throttle

const ThrottledInput = ({ onChange, delay = 500 }) => {
  const t = useRef()

  const handleChange = ({ target }) => {
    if (!t.current) {
      t.current = setTimeout(() => {
        onChange(target.value)
        clearTimeout(t.current)
        t.current = null
      }, delay)
    }
  }

  return (
    <input
      placeholder="throttle"
      onChange={handleChange}
    />
  )
}

// Debounce

const DebouncedInput = ({ onChange, delay = 500 }) => {
  const t = useRef()

  const handleChange = ({ target }) => {
    clearTimeout(t.current)
    t.current = setTimeout(() => onChange(target.value), delay)
  }

  return (
    <input
      placeholder="debounce"
      onChange={handleChange}
    />
  )
}

// ----

ReactDOM.render(<div>
  <ThrottledInput onChange={console.log} />
  <DebouncedInput onChange={console.log} />
</div>, document.getElementById('root'))

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

4voto

Aliaksei Points 117

Et une autre mise en œuvre. Un crochet personnalisé :

function useThrottle (func, delay) {
  const [timeout, saveTimeout] = useState(null);

  const throttledFunc = function () {
    if (timeout) {
      clearTimeout(timeout);
    }

    const newTimeout = setTimeout(() => {
      func(...arguments);
      if (newTimeout === timeout) {
        saveTimeout(null);
      }
    }, delay);

    saveTimeout(newTimeout);
  }

  return throttledFunc;
}

et l'utilisation :

const throttledFunc = useThrottle(someFunc, 200);

J'espère que cela aidera quelqu'un.

4voto

Rahul Gupta Points 1957

Vous pouvez utiliser useMemo pour optimiser votre gestionnaire d'événements accélérés

Exemple de code ci-dessous :

const App = () => {
  const [value, setValue] = useState(0);

  // ORIGINAL EVENT HANDLER
  function eventHandler(event) {
    setValue(value + 1);
  }

  // THROTTLED EVENT HANDLER
  const throttledEventHandler = useMemo(() => throttle(eventHandler, 1000), [value]);

  return (
    <button onClick={throttledEventHandler}>Throttled Button with value: {value}</button>
  )
}

3voto

Engr.MTH Points 197

En utilisant la fonction debounce de lodash, voici ce que je fais :

import debounce from 'lodash/debounce'

// The function that we want to debounce, for example the function that makes the API calls
const getUsers = (event) => {
// ...
}

// The magic!
const debouncedGetUsers = useCallback(debounce(getUsers, 500), [])

Dans votre JSX :

<input value={value} onChange={debouncedGetUsers} />

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X