首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >对事件处理程序的useCallback()和useEffect进行重新呈现

对事件处理程序的useCallback()和useEffect进行重新呈现
EN

Stack Overflow用户
提问于 2021-01-23 02:56:06
回答 2查看 1.4K关注 0票数 0

我正在学习从helinski fsopen20的反应。其中一个练习需要单击一个按钮并显示该按钮绑定区域的天气。

该按钮有一个onClick事件,该事件以区域索引作为参数来确定所选择的区域(很明显)。

代码语言:javascript
复制
<button onClick={() => onClickShow(i)}>{showBox.includes(i) ? myfunction(i): 'show'}</button>

然后,OnClick函数呈现上述区域的详细信息。需要获取的数据是在此函数中完成的。

代码语言:javascript
复制
const myfunction = useCallback((i)=>{ // the 'i' is passed
    
      axios.get('http://api.weatherstack.com/current'
      + `?access_key=${process.env.REACT_APP_API_KEY}`
      +`&query=${searchResult[i].name}`)
      .then(response=>{
        setWeather(response.data)
      })
      console.log(weather); //this re-renders to infinity
      
    return[
      <h2 key='name'>{searchResult[i].name}</h2>,
      <h2 key='sth'>Capital weather: {weather}</h2> // I will beautify this function later
    ]
   },[searchResult, weather])

   useEffect(()=>{

  },[myfunction])

我能够实现我想要的,但它需要大量的重新渲染。

最初,在不使用useEffect或useCallback的情况下使用axios ()会导致无限重呈现,但令人惊讶的是

我尝试过useEffect和useCallBack(),但是没有什么能阻止重呈现。

在sidenote上,我在我的中使用了一个不同的useEffect,它只呈现一次很好的效果。

如何正确地将useEffect与onClick这样的均衡器函数结合使用?

以下是完整的代码:

代码语言:javascript
复制
import React,{useState, useEffect, useCallback} from 'react'
import axios from 'axios'

const Helper=({searchResult})=>{

  const [showBox, setShowBox] = useState([])
  const [weather, setWeather] = useState([])


  const onClickShow = (index) => setShowBox(showBox.concat(index))

  
  const myfunction = useCallback((i)=>{
    
      axios.get('http://api.weatherstack.com/current'
      + `?access_key=${process.env.REACT_APP_API_KEY}`
      +`&query=${searchResult[i].name}`)
      .then(response=>{
        setWeather(response.data)
      })
      console.log(weather); /////// INFINTE RE-RENDER
      
    return[
      <h2 key='name'>{searchResult[i].name}</h2>,
      <p key='capital'>{searchResult[i].capital}</p>,
      <p key='popn'>{searchResult[i].population}</p>,
      <h3 key='langs'>Languages</h3>,
      <ul key='lang'>{searchResult[i].languages.map(lang => <li key={lang.iso639_1}>{lang.name}</li>)}</ul>,
      <img key='img' src={searchResult[i].flag} alt="flag" width="100" height="100" object-fit="fill"/>



    /*   searchResult.map(result=><h2 key={result.population}>{result.name}<br/></h2>),
    //   searchResult.map(result=><p key={result.population}> {result.capital} <br/> {result.population}</p>),
    //   <h3 key="id">Languages</h3>,
    //   searchResult.map(result=> <ul key={result.population}>{result.languages.map(lang => <li key={lang.iso639_1}>{lang.name}</li>)}</ul>),
    //   searchResult.map(result=><img src={result.flag} alt="flag" width="100" height="100" object-fit="fill" key={result.population}/>)
    */
    ]
   },[searchResult, weather])
   useEffect(()=>{

  },[myfunction])
   

  
  if(searchResult.length === 1){
      return(
        <div>
          {myfunction(0)}
        </div>
    )
  }
  else{
    return(
      <>
    {
        searchResult.length <= 10 ? 
        searchResult.map((result,i) => <h3 key={result.name}> {result.name} 
        <button onClick={() => onClickShow(i)}>{showBox.includes(i) ? myfunction(i): 'show'}</button></h3>)
        : searchResult
      }
        
          
      
      </>
    )
  }

  
}


const App =()=>{
  /// store all countries fetched
  const [countries, setCountries] = useState([])

  // store each searched country
  const [searchName, setSearchName] = useState([])
  
  //store the result country
  const [searchResult, setSearchResult] = useState([])



  useEffect(()=>{
    axios.get('https://restcountries.eu/rest/v2/all')
    .then(response=>{
      setCountries(response.data)
    })
   
  }, [])

  const handleSearch = (event) =>{
    setSearchName(event.target.value)
    if (searchName.length !== 0){

      var found = searchName ? countries.filter(country => country.name.toUpperCase().includes(searchName.toUpperCase())) : countries
      if(found.length > 10){
        setSearchResult("Too many matches, specify another filter")
      }
      else if(found.length === 1){
        setSearchResult(found)
      }
      else if(found.length === 0){
        setSearchResult(found)
      }
      else{
        setSearchResult(found)
      }
     
    }

  }


  

  return(
    <>

    <h1>find countries <input value={searchName} onChange={handleSearch} /></h1>
    <Helper searchResult={searchResult} />
    </>
  )
}

export default App;
EN

Stack Overflow用户

发布于 2021-01-23 03:15:21

之所以会发生这种情况,是因为在usecallback的依赖数组中,您传递的是weather,而在函数中,您正在设置状态weather。因此,它将第一次被调用,并将设置状态,即现在更新天气,这反过来将触发usecallback,因为它将记忆一个函数,并且每当任何一个依赖数组元素的值更新时,它都会被调用。

这种情况也将继续下去。为了解决这个问题,要么可以从数组中删除weather,要么可以从usecallback.But中提供一个空数组--在您的示例中,api调用依赖于searchResult.So --它应该存在于依赖数组中,以便在值更改时触发调用。

代码语言:javascript
复制
const myfunction = useCallback((i)=>{ // the 'i' is passed
    // axios call and return statement
   },[searchResult])  // <<<<<<<<<<<<<<<<<<<< weather has been removed

   useEffect(()=>{

  },[myfunction])

有关usecallback的更多信息

  1. link1
  2. link2
票数 0
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65855274

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档