Reputation:
I have a component of this type. For simplicity, I have removed all unnecessary code.
This component displays a button when clicking on which the value of the variable I declared in ComponentWillMount
should be displayed in the console, but when clicked, the console displays undefined, why?
'use strict';
class LoginFormComponent extends React.Component {
handleSubmit() {
console.log(this.model); //undefined
}
componentWillMount() {
this.model = 123;
}
render() {
console.log(this.model); //123
var styles = this.props.styles;
return (
<CM.MUI.FlatButton
style={styles.buttonStyle}
onClick={this.handleSubmit}
label={CM.gettext('Login')}/>
);
}
};
module.exports = LoginFormComponent;
Upvotes: 2
Views: 480
Reputation: 167182
You should be using componentDidMount
for setting up the instance properties as the content in componentWillMount
will not be in the instance scope as the component isn't mounted yet.
Also, use a =>
fat arrow function to get the access to this
instance of your component.
Updated Code:
class LoginFormComponent extends React.Component {
handleSubmit = () => {
console.log(this.model); // 123
}
componentDidMount() {
this.model = 123;
}
render() {
console.log(this.model); //123
var styles = this.props.styles;
return (
<CM.MUI.FlatButton
style={styles.buttonStyle}
onClick={this.handleSubmit}
label={CM.gettext("Login")}
/>
);
}
}
export default LoginFormComponent;
Console
Demo: agitated-solomon-3rrow - CodeSandbox
More information
As explained in this demo: summer-violet-g4pyd - CodeSandbox, it looks like the way React works is as follows:
So after the render()
is executed, the componentDidMount
is getting executed and there's no change after any state change.
If you want something to be there, please put them in constructor()
.
Moreover, componentWillMount
is deprecated and you should not use that in the next releases.
Upvotes: 4
Reputation: 65
I think this.modal
refers to the FlatButton component instead, can you bind the handleSubmit
to LoginFormComponent?
class LoginFormComponent extends React.Component {
constructor(props) {
super(props);
// This binding is necessary to make `this` work in the callback
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit() {
...
Upvotes: 1
Reputation: 163
First, model
seems to be a used as a state field, so as stated in the React
docs :
Typically, in React constructors are only used for two purposes:
- Initializing local state by assigning an object to this.state.
- Binding event handler methods to an instance.
You should not call setState() in the constructor(). Instead, if your component needs to use local state, assign the initial state to this.state directly in the constructor:
So you should first define your state using:
constructor(props) {
this.state.model = 123; // or
this.state = { // commonly used syntax
model : 123
}
}
Then still according to the docs :
UNSAFE_componentWillMount() is invoked just before mounting occurs. It is called before render(), therefore calling setState() synchronously in this method will not trigger an extra rendering. Generally, we recommend using the constructor() instead for initializing state.
You are indeed using this to initialize your component's state. As pointed by others, you should instead use ComponentDidMount
and use this.setState
to modify the state as modifying the state directly with this.state.model
is considered bad behaviour
Constructor is the only place where you should assign this.state directly. In all other methods, you need to use this.setState() instead.
Please check : https://reactjs.org/docs/react-component.html for more informations
Upvotes: 1
Reputation:
Because by writing onClick = {this.handleSubmit}
you detach the function from the context, and in this function you have this - not your component
Try to write
onClick = {this.handleSubmit.bind (this)}
or
handleSubmit = () => {console.log (this.model)}
Upvotes: 2
Reputation: 21317
Code declared in componentWillMount
will not be in the instance scope for a simple reason: The component isn't mounted yet. If you want to declare a global property in your class, just use componentDidMount
or declare it inside the class body like any other method.
Upvotes: 1