简体   繁体   中英

Login page showing initiially before rerender - Reactjs

What's happening is when my user is logged in and refreshes the page, my login page shows up briefly before showing them the actual page. I'd like either a blank page to show up or a loading page to show up instead in the mean time. I'm actually not quite sure why it's even showing up first because I have some data processing happening in componentWillMount() first.

Here's the relevant code:

componentWillMount()
{
    let url = "src/php/login.php";

    axios.get(url, {
        params: {
            get_userid : ""
        }
    })
    .then( r => 
    {
        if (r.data)
        {
            console.log(r.data);
            this.props.dispatch({ type: "new_user_id", payload: { id: r.data } });
        }
    })
    .catch( error => console.log(error));       
}



render() {
    var { user_id } = this.props;
    if (!user_id)
    {
        return (
            <div>
                some login logic
                <button onClick={this.new_user_id}>New user</button>

                <div style={{color : "red"}}>
                    { this.state.error && "Could not validate username/password. Please check." }
                </div>

                <form onSubmit={this.handle_submit}>
                    <div>
                        Username: <input id="username" name="username" type="text" />
                    </div>
                    <div>
                        Password: <input id="password" name="password" type="password" />
                    </div>
                    <input type="submit" value="submit" />
                </form>
            </div>
        );
    }

    else
    {
        return (
            <div style={{padding: "0 5px"}}>
                User ID: {user_id}
                <div style={{padding: "5px 0"}}>
                    <Link activeClassName="active" className="default bottom-radius" to='main'>Main Menu</Link>
                    <Link activeClassName="active" className="default bottom-radius" to='search'>Search</Link>
                    <Link activeClassName="active" className="default bottom-radius" to="form">Form</Link>
                    <a className="bottom-radius" style={{ float: "right", color : "blue", backgroundColor: "red", padding: "5px", cursor : "pointer" }} onClick={this.logout}>Logout</a>
                </div>
                <div style={{paddingTop: "10px"}}>
                    {this.props.children}
                </div>

            </div>
        );
    }
  }

user_id is intially ""

In your componentWillMount() function you have data processing in Promise so React continues to render w/o waiting for promise to resolve/reject.

To show blank page or any loading state you have to have some flag defined, eg:

state: {loading: true}

You can add loading state flag in constructor of your component like this:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {loading: true};
  }
}

then in your render method have checking of state:

render(){
   ...
   if(this.state.loading){
       return <div>Loading</div>;
   }
   ...
   // all your normal render stuff.
}

and in componentWillMount() after promise resolves set loading to false, if rejects also to false + some error message in same way.

The simple reason is, that the component is mounted and rendered before your ajax request is completed. A typical solution is to show some sort of a loading indicator while component data is being fetched.

Basically you need to implement a isLoading flag either in component state or in the reducer.

For example like this

const ExampleComponent extends Component() {
  constructor() {
    super(props)
    this.state = { isLoading: true }
  }
  componentWillMount() {
    // does and ajax operation, returns a promise
    fetchComponentData()
      .then(() => this.setState({ isLoading: false }))
  }
  render() {
    return (
      {
        this.props.user_id ? (
          <RegularContent />
        ) : (
          this.state.isLoading ? (
            <LoadingIndicator />
          ) : (
            <LoginForm />
          )
        )
      }
    )
  }
}

I also recommend reading about the React Component lifecycle , this gives you a good overview on some dos and don'ts for the lifecycle hooks like componentWillMount , componentDidMount , etc. For example it is recommended that componentDidMount be used for launching any ajax requests for component data instead of componentWillMount .

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM