Ad
React Fetch And Setting State
I'm trying to redirect a login page to a members page after it has retrieved authentication from a rest service:
this is my 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(function(response){
if(response.ok){
console.log(response.headers.get('Authorization'));
this.setState({clientToken: response.headers.get('Authorization')});
}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);
but when the fetch function returns and I obtain the data from the Authorization header I can't call this.setState() because it throws:
TypeError: Cannot read property 'setState' of undefined
at index.js:47
Any suggestions about how to solve this? Thanks!
Ad
Answer
This is because this
resolves to anonymous function (Object) that you created:
.then(function(response){ // you create a function/Object
if(response.ok){
console.log(response.headers.get('Authorization'));
this.setState({clientToken: response.headers.get('Authorization')}); // `this` is the anonymous function not React component
}else{
console.log(response.statusText);
}
})
For the same reason, you have bind
ed class functions in a constructor.
If you can use arrow function, this way this
will use context in which the arrow function is used - which will be your Login component:
.then((response) => { // you create a function/Object
if(response.ok){
console.log(response.headers.get('Authorization'));
this.setState({clientToken: response.headers.get('Authorization')}); // `this` is the anonymous function not React component
}else{
console.log(response.statusText);
}
})
Ad
source: stackoverflow.com
Related Questions
- → Import statement and Babel
- → should I choose reactjs+f7 or f7+vue.js?
- → Uncaught TypeError: Cannot read property '__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined
- → .tsx webpack compile fails: Unexpected token <
- → React-router: Passing props to children
- → ListView.DataSource looping data for React Native
- → React Native with visual studio 2015 IDE
- → Can't test submit handler in React component
- → React + Flux - How to avoid global variable
- → Webpack, React & Babel, not rendering DOM
- → How do I determine if a new ReactJS session and/or Browser session has started?
- → Alt @decorators in React-Native
- → How to dynamically add class to parent div of focused input field?
Ad