Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to fetch multiple URLs (non-constant number) at once? #83

Closed
supermihi opened this issue Aug 21, 2019 · 9 comments
Closed

How to fetch multiple URLs (non-constant number) at once? #83

supermihi opened this issue Aug 21, 2019 · 9 comments

Comments

@supermihi
Copy link

Say I need to fetch a list of remote resources, while the length on the list depends on the current props. (How) can I achieve that with use-http? As far as I understand the documentation of react, the number of hooks in a component needs to be constant.

@alex-cory
Copy link
Collaborator

alex-cory commented Aug 22, 2019

I'm assuming you're talking about pagination? You could do something like

const SomeComp = ({ page, pageLength }) => {
  const [list, setList] = useState([])
  const { get, loading } = useFetch('url')

  const fetchList = async () => {
    const theList = await get(`?page=${page}&pageLength=${pageLength}`)
    setList(theList)
  }

  const mounted = useRef(false)
  useEffect(() => { // componentDidMount
    if (!mounted.current) {
      fetchList()
      mounted.current = true
    }
  }, [])

  return <div>{list.map(item => <div>{item.text}</div>)}<div>
}

Does this make sense? Or are you asking something else?

@supermihi
Copy link
Author

Sorry for being unclear. What I actually am trying to do is load multiple URLs at once:

const SomeComp = ({urls}) => {
  const images = // fetch all the urls
  return images.map(/* do something with the results*/)
}

However I understand now that I can probably solve it like this:

const [results, setResults] = useState([])
const request = useFetch()
async function fetchStuff() {
    for (const url of urls) {
        const result = await request.get(url)
        setResults([...results, result])
    }
  }
useEffect(() => { fetchStuff() })

@alex-cory
Copy link
Collaborator

You can do that, however it's always recommended that you don't have api calls/awaits in loops. Why do you need to make an api call for image urls? If you're displaying images, why not just do imageUrls.map(url => <img src={url} />)

@supermihi
Copy link
Author

In my application I am fetching data, not images – that was just for the example.

@alex-cory
Copy link
Collaborator

You could do something like

const Comp = (props) => {
  const [imagesData, setImagesData] = useState([])
  const [loading, setLoading] = useState(false)
  const { get } = useFetch('url')

  const getImageData = useCallback(async () => {
    setLoading(true)
    const imgData = await images.map(async image =>  await get('/image?id=${image.id}'))
    setImagesData(imgData)
    setLoading(false)
  }, [props.images, imagesData, setImagesData, setLoading])

  const mounted = useRef(false)
  useEffect(() => {
    if (!mounted.current) { // on mount
      getImagesData()
    }
  }, [getImagesData])

  return (
    <>
      {loading && 'Loading...'}
      {imagesData.length > 0 && imagesData.map(img => <img src={img.url} />)}
    </>
  )
}

Is this something like what you're looking for?

@alex-cory
Copy link
Collaborator

@supermihi is your question answered? Gonna close this if it is :)

@supermihi
Copy link
Author

@alex-cory thanks for your answer. The above should work (though I'd remove the mounted construct, which would prevent re-loading if props.images changes, right?).
However I don't really see the benefit of useFetch here, as opposed to calling fetch directly?

@alex-cory
Copy link
Collaborator

alex-cory commented Sep 11, 2019

Oh yeah, that makes sense about the mounted part. In this case, the only benefit would be if you used the <Provider url='https://example.com'><App /></Provider>. Kind of like how axios works. Also, if you have authentication, you could handle that at the top level in addition to the syntax is a bit cleaner. Having the global fetch config is pretty nice.

@supermihi
Copy link
Author

Ok, thanks a lot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants