简体   繁体   中英

Proper use of UseCallBack

Currently, my code re-renders every time the query parameter is updated. Once I remove the query parameter; however, I get a warning stating "React Hook useCallback has a missing dependency: 'query'. Either include it or remove the dependency array react-hooks/exhaustive-deps". I have tried just defining my getData function within the useEffect, but I am using getData as on onclick function outside of the useEffect. What I am trying to accomplish is to initially fetch articles on react hooks and then only fetch new data on submit as opposed to when the query is updated and not have any warnings about query being a missing dependency as well. Any suggestions would help immensely. the code is as follows:

import React, { useState, useEffect, useCallback } from "react"
import axios from "axios"

const Home = () => {
  const [data, setData] = useState(null)
  const [query, setQuery] = useState("react hooks")

  const getData = useCallback(async () => {
    const response = await axios.get(
      `http://hn.algolia.com/api/v1/search?query=${query}`
    )
    setData(response.data)
  }, [query])

  useEffect(() => {
    getData()
  }, [getData])

  const handleChange = event => {
    event.preventDefault()
    setQuery(event.target.value)
  }

  return (
    <div>
      <input type='text' onChange={handleChange} value={query} />
      <button type='button' onClick={getData}>
        Submit
      </button>
      {data &&
        data.hits.map(item => (
          <div key={item.objectID}>
            {item.url && (
              <>
                <a href={item.url}>{item.title}</a>
                <div>{item.author}</div>
              </>
            )}
          </div>
        ))}
    </div>
  )
}

export default Home

Add a submitting state as a condition for triggering your axios request

  const [submitting, setSubmitting] = useState(true)
  const [data, setData] = useState(null)
  const [query, setQuery] = useState("react hooks")

  useEffect(() => {
    const getData = async () => {
      const response = await axios.get(
        `http://hn.algolia.com/api/v1/search?query=${query}`
      )
      setData(response.data)
      setSubmitting(false) // call is finished, set to false
    }

    // query can change, but don't actually trigger 
    // request unless submitting is true

    if (submitting) { // is true initially, and again when button is clicked
      getData()
    }
  }, [submitting, query])

  const handleChange = event => {
    event.preventDefault()
    setQuery(event.target.value)
  }

  const getData = () => setSubmitting(true)

If you wanted to useCallback , it could be refactored as such:

  const [submitting, setSubmitting] = useState(true)
  const [data, setData] = useState(null)
  const [query, setQuery] = useState("react hooks")

  const getData = useCallback(async () => {
    const response = await axios.get(
      `http://hn.algolia.com/api/v1/search?query=${query}`
    )
    setData(response.data)
  }, [query])

  useEffect(() => {
    if (submitting) { // is true initially, and again when button is clicked
      getData().then(() => setSubmitting(false))
    }
  }, [submitting, getData])

  const handleChange = event => {
    event.preventDefault()
    setQuery(event.target.value)
  }

and in render

<button type='button' onClick={() => setSubmitting(true)}>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM