user20112858
user20112858

Reputation: 89

usestate can change the state value after axios in useEffect

I expected to get the url with category=business,but the web automatically reset my state to the url that dosent have the category.I dont know the reason behind

 let {id}=useParams()
 

     const [newsurl,setNewsurl]=useState(()=>{
        const initialstate="https://newsapi.org/v2/top-headlines?country=us&apiKey=c75d8c8ba2f1470bb24817af1ed669ee"
        return initialstate;})
      //console.log(id);
      const [articles, setActicles] = useState([]);
      useEffect( ()=>{
        
        if(id === 2)
          console.log("condition")
          setNewsurl("https://newsapi.org/v2/top-headlines?country=de&category=business&apiKey=c75d8c8ba2f1470bb24817af1ed669ee")},[])  
       
        useEffect(() => {
          const getArticles = async () => {
            
            const res = await Axios.get(newsurl);
            setActicles(res.data.articles);
            console.log(res);
          };
          getArticles();
        }, []);
        useEffect(() => {
          console.log(newsurl)
     

         // Whatever else we want to do after the state ha
    
    s been updated.
       }, [newsurl])
    
      
                //return "https://newsapi.org/v2/top-headlines?country=us&apiKey=c75d8c8ba2f1470bb24817af1ed669ee";}
     
      return (<><Newsnavbar />{articles?.map(({title,description,url,urlToImage,publishedAt,source})=>(
        <NewsItem 
    title={title} 
    desciption={description} 
    url={url} 
    urlToImage={urlToImage}
    publishedAt={publishedAt}
    source={source.name} /> 
))  } </>

  )

one more things is that when i save the code the page will change to have category but when i refresh it ,it change back to the inital state.Same case when typing the url with no id.May i know how to fix this and the reason behind?

Upvotes: 1

Views: 1049

Answers (2)

tomleb
tomleb

Reputation: 2525

Setting the state in React acts like an async function.
Meaning that the when you set the state and put a console.log right after it, it will likely run before the state has actually finished updating.

You can instead, for example, use a useEffect hook that is dependant on the relevant state in-order to see that the state value actually gets updates as anticipated.

Example:

useEffect(() => {
   console.log(newsurl)
   // Whatever else we want to do after the state has been updated.
}, [newsurl])

This console.log will run only after the state has finished changing and a render has occurred.

  • Note: "newsurl" in the example is interchangeable with whatever other state piece you're dealing with.

Check the documentation for more info about this.

Upvotes: 1

abolfazl shamsollahi
abolfazl shamsollahi

Reputation: 785

setState is an async operation so in the first render both your useEffetcs run when your url is equal to the default value you pass to the useState hook. in the next render your url is changed but the second useEffect is not running anymore because you passed an empty array as it's dependency so it runs just once. you can rewrite your code like the snippet below to solve the problem.

  const [articles, setActicles] = useState([]);
  const Id = props.id;

  useEffect(() => {
    const getArticles = async () => {
      const newsurl =
        Id === 2
          ? "https://newsapi.org/v2/top-headlines?country=de&category=business&apiKey=c75d8c8ba2f1470bb24817af1ed669ee"
          : "https://newsapi.org/v2/top-headlines?country=us&apiKey=c75d8c8ba2f1470bb24817af1ed669ee";
      const res = await Axios.get(newsurl);
      setActicles(res.data.articles);
      console.log(res);
    };
    getArticles();
  }, []);

Upvotes: 0

Related Questions