简体   繁体   中英

How to fire the function useEffect after clicking event?

Recently am learning React hooks and am now doing a search app which have to call API then return the list movies correspond to what i type in the search box.

My code here:

useFetch.js

import { useState, useEffect } from 'react'

export const useFetch = (url, initialState) => {
    const [data, setData] = useState(initialState)
    const [loading, setLoading] = useState(true)
    useEffect(() => {
        async function fetchMovies() {
            const response = await fetch(url)
            const data = await response.json()
            setData(data.Search)
            setLoading(false)
        }
        fetchMovies()
    }, [url])

    return { data, loading }
}

App.js

import React, { useState } from 'react'
import Search from './components/Search'
import Result from './components/Result'
import Loading from './components/Loading'
import { useFetch } from './utils/useFetch'

export default function App() {
    const [key, setKey] = useState('Iron man')
    const onSearch = (key) => {
        setKey(key)
    }
    const {data, loading} = useFetch(`https://www.omdbapi.com/?s=${key}&apikey=${API_KEY}`)

    return (
        <>
            <Search handleSearch={onSearch}/>
            <Loading isLoading={loading} />
            <Result movies={data}/>
        </>
    )
}

As far as i understand after clicking button search function call API will be fired and return the result as expect. I can't put

const {data, loading} = useFetch(`https://www.omdbapi.com/?s=${key}&apikey=${API_KEY}`)

inside onSearch function. Follow the code function call API is automatically called whenever the app start and return undefined as result.

Can anyone help me out and explain why?

You are correct in your understanding of how hooks can only be called at the top level in a react component. Make the following changes and the API won't get called the first time around but will get called subsequently.

  1. Use url state variable and extract generateUrl logic outside the component:
function generateUrl(key) {
  return `https://www.omdbapi.com/?s=${key}&apikey=${API_KEY}`
}

function MyComponent() {
  const [url, setUrl] = React.useState('');
  //...
}
  1. Check for url presence in useFetch hook by wrapping fetchMovies() call in an if condition. This way, API won't trigger since default value of url is empty.
import { useState, useEffect } from 'react'

export const useFetch = (url, initialState) => {
    const [data, setData] = useState(initialState)
    const [loading, setLoading] = useState(true)
    useEffect(() => {
        async function fetchMovies() {
            const response = await fetch(url)
            const data = await response.json()
            setData(data.Search)
            setLoading(false)
        }

        if(url) {
          fetchMovies()
        }
    }, [url])

    return { data, loading }
}
  1. Finally, modify onSearch
const onSearch = (key) => {
   setUrl(generateUrl(key))
}

也许您可以通过以下方式公开setUrl

return { data, loading, onSearch: (key) => setUrl(generateUrl(key)) }

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