Search code examples
reactjsapireact-hooksuse-effectuse-state

setState doesn't set immidaltly after a fetch API method


I've read in here a lot of the same question and I apply what works for everybody but it not seems to work for me . I try to fetch data from my API but even with the UseEffect hook my setList don't want to set ListVille. This is my code, do you have an idea why ?

import React, {useEffect, useState} from 'react';
import {Navigate} from 'react-router-dom'
import Entete from './MEP/entete'

function Localisation() {
  const [CP, setCP]= React.useState('');
  const [city, setCity]= React.useState('');
  const [ListVille, setList]= React.useState();
  const [goToExploit, setGoToExploit] = useState(false)

  useEffect ( (CP, ListVille) => {
    fetch('http://localhost:3000//api/1.0/getCommunes/'+ CP )
      .then( (response) => {
        console.log(response)
        return response.json()
      })
      .then(response =>{
        setList(response)
        console.log(response)
        console.log(ListVille)
      }) 
  })

  function handleSubmit(event) {
    event.preventDefault()
    setGoToExploit(true)
  }

  if(goToExploit) {
      return <Navigate push to={`/exploitation`} />
  }

  function handleChange(event) {
    var CP = event.target.value
    setCP(CP)      
 }

  return (
    <div>
      <Entete titre="Localisation"/>

      <form onSubmit={handleSubmit}>
        <div className='titre'> Saisissez votre code postal {CP}</div>
        <input 
        className='input'
        value={CP}
        onChange={handleChange}
        placeholder='Code Postal'
        type='text'
        required/>
        {/*<div className='paragraphe'> Test {CP==='41160' ? ListVille[0].key : 'coucou'}</div>*/}
        <div className='centrer'>
          <button type='submit' className='validation'> Valider </button>
        </div>
      </form>
    </div>
  );
}

export default Localisation;

I don't use the

useEffect ( () => {
...
}, [] ) 

because I want the useffect to apply everytime the CP changes


Solution

  • First set a state in react is an asynchronous operation, so

        setList(response)
        console.log(response)
        console.log(ListVille)
    

    console will show the old value of ListVille

    If you want the current value, you can see it inside the prev value of set state.

    setList(response)
    console.log(response)
    setList(prev => {
      console.log(prev)
      return prev;
    })
    

    Second, using useEffect without an array of dependencies will run on each component render, so if you want to call this function on the component mount, you need to set an empty array of dependencies.