-->

React app componentDidMount rendering twice

2019-08-20 17:54发布

问题:

I've got a simple react app that has a Login that receives a Json Web Token on successful authentication and the passes it to a sibling component (Members) that in its componentDidMount uses this JWT to make a fetch call to the server. The thing is that componentDidMount is being called twice, the first one with undefined JWT and the second time with the retrieved JWT. Heres my code:

App (parent code):

class App extends Component{
  state = {
    clientToken: ''
  }

  callbackGetToken = (token) => {
    this.setState({clientToken: token});
  }


  render(){
    return(
      <Switch>
        <Route exact path="/" component={props => <Login sendToken = {this.callbackGetToken}/>}/>
        <Route exact path="/members" component={props => <Members authToken = {this.state.clientToken}/>}/>
      </Switch>
    )
  }
};

export default App;

Login component:

class Login extends Component {

  state = {
    credentials:{
      "username": "", 
      "password": ""
    },
    clientToken: ""
  }

  constructor(props){
    super(props);
    this.handleUsernameChange = this.handleUsernameChange.bind(this);
    this.handlePasswordChange = this.handlePasswordChange.bind(this);
    this.handleFormSubmit = this.handleFormSubmit.bind(this);
  }

  handleUsernameChange(event){
    this.state.credentials.username = event.target.value;
  }


  handlePasswordChange(event){
    this.state.credentials.password = event.target.value;
  }

  handleFormSubmit(event){
    event.preventDefault();
    const data = JSON.stringify(this.state.credentials);

    fetch(loginFormurl, {
      method: 'POST',
      headers: {
        "Content-Type": "application/json"
      },
      body: data,
    })
    .then((response) => {
      if(response.ok){
        const token = response.headers.get('Authorization');
        console.log(token);
        this.setState({clientToken: token});
        this.props.sendToken(token);
      }else{
        console.log(response.statusText);
      }
    })

    .catch(function(error) {
      console.log(error);
    });
  }

  render() {
    if (this.state.clientToken !== "") {
      return <Redirect to='./members' />;
    }

    return (
      <div className="App">
        <h1 className="Login-title">Login to Social Media Aggregator</h1>
        <form className="Login-box" onSubmit={this.handleFormSubmit}>
          <p>
            <label>
              Username
              <input id="username" type="text" name="username" required onChange={this.handleUsernameChange}/>
            </label>
          </p>
          <p>
            <label>
              Password
              <input id="password" type="password" name="password" autoComplete="password" required  onChange={this.handlePasswordChange}/>
            </label>
          </p>
          <p><input type="submit" value="Login"/></p>
        </form>
      </div>
    );
  }
}

export default withRouter(Login);

And the sibling Members component:

class Members extends Component{
    constructor(props){
        super(props);
        this.state = {
            interrests: [],
            authToken: props.authToken
        }
    }

    componentDidMount(){
        fetch(interestUrl, {
            method: 'GET',
            headers: {
              "Content-Type": "application/json",
              "Authorization": this.state.authToken
            }
          })
          .then((response) => {
            if(response.ok){
              console.log(response.json());
            }else{
              console.log(response.statusText);
            }
          })
    };

    render(){
        return(
            <div>
                <Menu/>
                <Main/>
            </div>
        )
    }

}
export default Members;

Any ideas on how to solve this? Thanks!

UPDATE:

Found the problem. It seems the Redirect component from Login is creating the Members component twice. If I remove the Redirect from the page and instead just put a Link to make the redirect, it renders just once as supposed to do. Still, don't know how to solve this though :(