Реагирующие хуки — как вызвать useEffect по требованию?

#reactjs #react-hooks

#reactjs #реагирующие хуки

Вопрос:

Я переписываю таблицу CRUD с помощью реактивных хуков. Пользовательский крючок useDataApi ниже предназначен для извлечения данных из таблицы, просмотра изменения URL-адреса — поэтому он будет запущен при изменении параметров. Но мне также нужно получить самые свежие данные после удаления и редактирования. Как я могу это сделать?

 const useDataApi = (initialUrl, initialData) => {
  const [url, setUrl] = useState(initialUrl)

  const [state, dispatch] = useReducer(dataFetchReducer, { data: initialData, loading: true })

  useEffect(() => {
    const fetchData = async () => {
      dispatch({ type: 'FETCH_INIT' })
      const result = await instance.get(url)
      dispatch({ type: 'FETCH_SUCCESS', payload: result.data })
    }

    fetchData()
  }, [url])

  const doFetch = url => {
    setUrl(url)
  }

  return { ...state, doFetch }
}
  

Поскольку url после удаления / редактирования значение остается неизменным, оно не будет запущено. Я думаю, у меня может быть инкрементный флаг, и пусть useEffect также отслеживает его. Но, возможно, это не лучшая практика? Есть ли лучший способ?

Ответ №1:

Все, что вам нужно сделать, это извлечь fetchData метод из useEffect и вызвать его, когда он вам понадобится. Также убедитесь, что вы передаете функцию как параметр в массиве зависимостей.

 const useDataApi = (initialUrl, initialData) => {
  const [url, setUrl] = useState(initialUrl)

  const [state, dispatch] = useReducer(dataFetchReducer, { data: initialData, loading: true })

  const fetchData = useCallback(async () => {
      dispatch({ type: 'FETCH_INIT' })
      const result = await instance.get(url)
      dispatch({ type: 'FETCH_SUCCESS', payload: result.data })
  }, [url]);

  useEffect(() => {
    fetchData()
  }, [url, fetchData]); // Pass fetchData as param to dependency array

  const doFetch = url => {
    setUrl(url)
  }

  return { ...state, doFetch, fetchData }
}
  

Комментарии:

1. Вы возвращаете fetchData из пользовательского hook и вызываете его в пользовательском действии

2. Не будет ли fetchData получать новое значение для каждого вызова useDataApi, чтобы он всегда вызывал useEffect?

3. Извините за мою ошибку, вам также нужно обернуть fetchData с помощью useCallback, чтобы он создавался снова только при изменении URL

4. Смотрите также это сообщение в блоге: overreacted.io/a-complete-guide-to-useeffect /…

5. Я предполагаю, что при использовании useCallback() тогда useEffect () больше не нужно указывать URL в своих deps, поскольку он неявно зависит от URL через fetchData?