2021年1月22日星期五

React useCallback() and useEffect on event-handler keeps re - rendering

I am learning react from helinski fsopen20. One of the exercises requires to click a button and show the weather of that button bound region.

The button has an onClick event that takes index of regions as the parameter to determine which region is selected (obviously).

<button onClick={() => onClickShow(i)}>{showBox.includes(i) ? myfunction(i): 'show'}</button>  

OnClick function then renders details for the said region. The data required to be fetched is being done inside this function

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])       

I am able to achieve what I want but it costs a lot of re-rendering.

Initially using axios get() WITHOUT useEffect or useCallback resulted in infinite re-render BUT to my surprise,

I have tried useEffect and useCallBack() but nothing is stopping the re-rendering.

On a sidenote, I am using a different useEffect inside my App component which renders once just fine.

How do I properly use useEffect with eventhandler function such as onClick?

Below is the complete code:

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;  
https://stackoverflow.com/questions/65855274/react-usecallback-and-useeffect-on-event-handler-keeps-re-rendering January 23, 2021 at 10:56AM

没有评论:

发表评论