点击事件后如何触发功能useEffect?

时间:2019-07-24 07:59:27

标签: reactjs react-hooks

最近我正在学习React钩子,现在正在做一个搜索应用程序,该应用程序必须调用API,然后返回与我在搜索框中键入的内容相对应的列表电影。

我的代码在这里:

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}/>
        </>
    )
}

据我了解,单击按钮搜索功能后,将触发调用API并按预期返回结果。我不能放

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

内部 onSearch 功能。遵循代码函数调用,只要应用程序启动并返回未定义的结果,就会自动调用API。

有人可以帮我解释一下吗?

2 个答案:

答案 0 :(得分:0)

您对如何仅在React组件的顶层调用挂钩的理解是正确的。进行以下更改,该API将不会首次调用,但随后会被调用。

  1. 使用url状态变量并在组件外部提取generateUrl逻辑:
function generateUrl(key) {
  return `https://www.omdbapi.com/?s=${key}&apikey=${API_KEY}`
}

function MyComponent() {
  const [url, setUrl] = React.useState('');
  //...
}
  1. 通过将url调用包装在if条件中,检查useFetch钩子中是否存在fetchMovies()。这样,由于url的默认值为空,因此API不会触发。
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. 最后,修改onSearch
const onSearch = (key) => {
   setUrl(generateUrl(key))
}

答案 1 :(得分:0)

也许您可以通过以下方式暴露setUrl

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