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
没有评论:
发表评论