Неверный вызов ловушки при попытке извлечь данные с помощью useCallback - PullRequest
0 голосов
/ 31 марта 2020

Я пытаюсь вызвать useState внутри функции asyn c, например:

const [searchParams, setSearchParams] = useState({});

const fetchData = () => useCallback(
    () => {
      if (!isEmpty(searchParams)) {
        setIsLoading(true); // this is a state hook
        fetchData(searchParams)
          .then((ids) => {
            setIds(ids); // Setting the id state here
          }).catch(() => setIsLoading(false));
      }
    },
    [],
  );

Есть два состояния, которые я пытаюсь установить внутри этой функции fetchData (setIsLoading и setIds), но всякий раз, когда эта функция выполняется, я получаю сообщение об ошибке:

Uncaught Error: Invalid hook hook. Хуки могут быть вызваны только внутри тела компонента функции. Это может произойти по одной из следующих причин: 1. У вас могут быть несовпадающие версии React и средства визуализации (например, React DOM). 2. Возможно, вы нарушаете правила хуков. 3. У вас может быть несколько копий React в то же самое приложение

Что это за правило хуков, которое я здесь нарушаю? Есть ли способ установить эти состояния из функции?

PS: здесь я использовал только ловушку useCallback для вызова этой функции с помощью lodash/debounce

Редактировать: функция вызывается внутри useEffect вроде:

const debouncedSearch = debounce(fetchSearchData, 1000); // Is this the right way to use debounce? I think this is created every render.

const handleFilter = (filterParams) => {
    setSearchParams(filterParams);
};

useEffect(() => {
    console.log('effect', searchParams); // {name: 'asd'}
    debouncedSearch(searchParams); // Tried without passing arguments here as it is available in state.
// But new searchParams are not showing in the `fetchData`. so had to pass from here.
}, [searchParams]);

1 Ответ

0 голосов
/ 31 марта 2020

Правило перехвата, которое вы нарушаете, касается useCallback, потому что вы возвращаете его как результат своих fetchData;

useCallback следует вызывать на верхнем уровне; не в обратном вызове, например:

const fetchData = useCallback(
    () => {
      if (!isEmpty(searchParams)) {
        setIsLoading(true); // this is a state hook
        fetchData(searchParams)
          .then((ids) => {
            setIds(ids); // Setting the id state here
          }).catch(() => setIsLoading(false));
      }
    },
    [],
  );

Код, который вы написали, эквивалентен

const fetchData = () => { return React.useCallback(...

или даже

function fetchData() { return React.useCallback(...

Чтобы узнать больше о том, почему вы не можете этого сделать, я настоятельно рекомендую сообщение в блоге .

изменить:

Чтобы использовать дебагованный searchParams, вам не нужно дебатировать функцию, которая выполняет вызов, а скорее дебатировать искомое значение. (и на самом деле вы вообще не используете функцию fetchData, которая вызывает React.useCallback, просто используйте ее прямо в вашем useEffect)

Я рекомендую использовать этот useDebounce хук для отката Ваш поисковый запрос

const [searchParams, setSearchParams] = React.useState('');
const debouncedSearchParams = useDebounce(searchParams, 300);// let's say you debounce using a delay of 300ms

React.useEffect(() => {
  if (!isEmpty(debouncedSearchQuery)) {
        setIsLoading(true); // this is a state hook
        fetchData(debouncedSearchParams)
          .then((ids) => {
            setIds(ids); // Setting the id state here
          }).catch(() => setIsLoading(false));
      }
}, [debouncedSearchParams]); // only call this effect again if the debounced value changes

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...