Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to fetch onChange from select value only when select ? is it possible without using useEfect?

So I was trying to fetch some anime data based on the options I have in select (genre),
the problem is that the fetch doesn’t happen onChange in my select only after changing option twice, I have tried to use useEffect but the problem with that it’s fetching immediately without changing the select value.

can someone help and explain what I’m doing wrong?

here is my code on codesandbox

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

index.js

function App() {
  const [list,setList]=useState([])
  const [genre,setGenre]=useState(0)


  const fetchData=()=>{
    const options = {
      method: 'GET',
      url: `https://jikan1.p.rapidapi.com/genre/anime/${genre}/1`,
      headers: {
        'x-rapidapi-host': 'jikan1.p.rapidapi.com',
        'x-rapidapi-key': '*******************************'
      }
    };
    
    axios.request(options).then(function (response) {
      console.log(response.data.anime);
      setList(response.data.anime)
    }).catch(function (error) {
      console.error(error);
    });
  }

    

  const handleChange=(e)=>{
    setGenre(e.target.value)
    fetchData()
    
  }
  
  return (
    <div className="mx-auto px-8 py-4 flex flex-col justify-center">

      <div>
      <h1>Design with Tailwind</h1>
      
      <select name="genre" className='p-2 bg-bg-prime'  id="genre"  onChange={handleChange}>
            <option value="1" >Action</option>
            <option value="2" >Adventure</option>
            <option value="4" >Comedy</option>
      </select>
      </div>
        <div>
          {list && (
            list.map((an)=>(
              <p key={an.title}>{an.title}</p>
            ))
          )}
        </div>
    </div>
  )
}

const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)

>Solution :

While you are calling fetchData after the setGenre, according to react docs :

State Updates May Be Asynchronous

So basically fetchData is called before the state value is actually updated (and this is causing your request to be performed with the old value instead of the requested one).
A fix would be something like:

...
useEffect(() => {
  fetchData();
}, [genre]) 

const handleChange=(e)=>{
  setGenre(e.target.value)
}

If you really want to keep your approach you could also do something like:

const handleChange=(e)=>{
  setGenre(e.target.value)
  fetchData(e.target.value)
}

and use the variable in fetch data (so

const fetchData = (selectedGenre) => {
  ...
    url: `https://jikan1.p.rapidapi.com/genre/anime/${selectedGenre}/1`,
  ...

I personally prefer first approach, but both should work.

Also if you use a valid value as the initial value for the genre along with the first approach you can get the list populated by default (for your example const [genre,setGenre]=useState(1) )

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading