React app componentDidMount rendering twice
Asked Answered
C

0

0

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 :(

Columbine answered 29/4, 2018 at 18:7 Comment(4)
You have two exact props being passed, I'm not 100% but I think the Switch gets confused. Remove the exact prop passed to /members.Cappuccino
@HenrikAndersson modifying second route to <Route path="/members" component={props => <Members authToken = {this.state.clientToken}/>}/> did nothing :(Columbine
Are you redirecting to /login and then back to /members, in that case the componentDidMount of member will be called twiceInsociable
@ShubhamKhatri I'm not too familiar with Route yet, but no, at least I'm not doing it explicitly. The login component is the entry point to the app, from where I do the redirect to Members through the <Redirect to='./members' />;Columbine

© 2022 - 2024 — McMap. All rights reserved.