0

I apologize for posting repeated question, but I wasn't able to get my code working after reading all previous answers.

In my code, I try to read the URL parameter with queryString and update state with it using setState(). All within componentDidMount() method.


import React, {Component} from 'react';
import ChartBox from "./chartBox";
import Header from "./header";
import Footer from "./footer";
import Greeting from "./greeting";
import Menu from "./menu";
import Navbar from "./navbar";
import queryString from "query-string";



class Body extends Component{
    constructor(props){
        super(props);
        this.state = {
            username:""
        };
    }


    componentDidMount(){
        let user = queryString.parse(this.props.location.search);
        this.setState({username: user});

        console.log(this.state.username);
        console.log(user.user);
    }

    render(){
        return(
       <div>
           <Header />
           <Navbar />
           <Greeting user = {this.state.username}/>
           <ChartBox user = {this.state.username}/>
           <Menu user = {this.state.username}/>
           <Footer />
       </div>
        )
    }
}

export default Body;

queryString works fine and gets the correct value to the user variable. this.setState({username: user}); does not update state - I don't understand why. {this.state.username} does not passundefined to child components even if I explicitly set the initial state to some value.

I've seen mention that it might be a scope issue, but on the other hand I see examples on the internet that are no different from mine. I'm totally confused now.

Any help is greatly appreciated.

Jack_loc
  • 45
  • 6
  • Does this answer your question? [can't setState in reactjs](https://stackoverflow.com/questions/59495222/cant-setstate-in-reactjs) – wentjun Jan 04 '20 at 04:33

2 Answers2

1

setState() is not guaranteed to be synchronous. this.state.username will update some time after componentDidMount() returns

x00
  • 13,643
  • 3
  • 16
  • 40
0

setState is asynchronous.

It means you can’t call setState on one line and assume state has changed on the next.

setState({ name: "Michael" });
console.log(this.state.name);  //it won't show current updated state

How you can check this?

setState({ name: "Michael" },()=>{
  console.log(this.state.name);
});

Here you can check you your state updated or not as a callback.

Demo https://codesandbox.io/s/asynchronous-fc9zx

akhtarvahid
  • 9,445
  • 2
  • 26
  • 29
  • Thank you for your answer. In this case, how do I pass the URL parameter as a prop to child components? – Jack_loc Jan 04 '20 at 05:26
  • @Jack_loc hey check demo app i mentioned how you can pass and access inside child component – akhtarvahid Jan 04 '20 at 05:29
  • Sorry Vahid Akhtar, but I can't understand the code in the sandbox you've mentioned. Probably, this is because I still know very little about React. – Jack_loc Jan 04 '20 at 23:13
  • Sorry Vahid Akhtar, but I can't understand the code in the sandbox you've mentioned. Probably, this is because I still know very little about React. I got rid of qyerySring and parsed URL manually. Transformed my component into functional and used useEffect to set state. All that worked. But as you've mentioned setState is async and updates after component renders which is no use for me. it gets passed as undefined to child components, they fetch database with undefined parameter. Only after that state in parent component gets updated. I guess I'll leave this idea until I learn more React. – Jack_loc Jan 04 '20 at 23:22