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

Dieguinho
  • 758
  • 2
  • 14
  • 31
  • 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`. – Henrik Andersson Apr 29 '18 at 18:29
  • @HenrikAndersson modifying second route to ` }/>` did nothing :( – Dieguinho Apr 29 '18 at 18:38
  • Are you redirecting to /login and then back to /members, in that case the componentDidMount of member will be called twice – Shubham Khatri Apr 30 '18 at 05:59
  • @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 `;` – Dieguinho Apr 30 '18 at 06:08

0 Answers0