Different ways to initialize the state in ReactJS - reactjs

It might be because of the speed that ReactJS is developing, or just some mis-information, but when reading articles about how to set the state, I usually come across different ways.
In the constructor
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { ... }
}
}
Directly in the class
class MyComponent extends React.Component {
state = { ... }
}
In ComponentWillMount
class MyComponent extends React.Component {
ComponentWillMount() {
this.state = { ... }
}
}
This diversity of options confuses me often, and makes it hard for me to decide how I should set the state in my components.
My question is: Is there any difference between these methods to set the state? If so, what are the advantages and disadvantages of each?

These are all basically the same thing, just syntactic sugar.
In the constructor
This is the "normal" standard way to attach a property to a class instance.
Directly in class
This is just a syntactic sugar and this is the class fields proposal which is in stage 3 at the moment (01/10/18). you will need babel/plugin-proposal-class-properties
In ComponentWillMount
Same as the constructor version but inside a life-cycle method of react (which is deprecated by the way).

You should now componentWillMount is deprecated and you should not use it. as for setting the state in the constructor or as class property is the same you can use either, I prefer the class property.

This is class field proposal:
class MyComponent extends React.Component {
state = { ... }
}
It is syntactic sugar for:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { ... }
}
}
The former is shorter and can be considered preferable in transpiled React application because of its brevity, unless there's a need for explicit constructor.
ComponentWillMount lifecycle hook was renamed to UNSAFE_componentWillMount and deprecated in favour of constructor:
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.

Related

use lifecycle in child component in react

I'm implementing an inherit action to archive my goal.
My goal is to call a lifecycle event in child component instead of parent one. That's what I can do in C# .net. How can I archive it? Is there any difference?
When I call lifecycle event in parent component, it works fine
Here's my code
class A extends React.Component {
render() {
return (
//......
)
}
}
class B extends A {
componentDidMount() {
console.log('componentDidMount') // didn't log here
}
componentDidUpdate(prevProps) {
console.log('componentDidUpdate:', prevProps) // didn't log here
}
}
Thanks all
This is quite tricky.
In JavaScript, a class cannot extend from multiple classes, which is also known as “multiple inheritance”. In JavaScript, objects can only be associated with a single prototype, and extending multiple classes would mean that an object associates with multiple prototypes, which is not possible.
Also, to have lifecycle methods, the class should extend React.Component.
So you can either extend React.Component or Component A.
Multiple inheritance doesn't allow in javascript by the time I'm writing this. And life-cycle event will work only if you extends React.Component. So, you should not extends another component in react. The recommended way is - use composition pattern instead of inheritance.
import B from './B';
class A extends React.Component {
render() {
return (
<B />
//.......
)
}
}
class B extends React.Component {
componentDidMount() {
console.log('componentDidMount')
}
componentDidUpdate(prevProps) {
console.log('componentDidUpdate:', prevProps)
}
}
Now it will work. Hope you will figure out the problem. For more please visit reactjs composition vs inheritance
the trick is to use super.componentDidMount() in the child component
componentDidMount() {
super.componentDidMount();
console.log('componentDidMount')
}
here you can find the working code
https://codesandbox.io/s/crazy-snow-1k9t2?file=/src/App.js

Where does "this.state" comes from when using TypeScript in React

I was wondering where does the property this.state comes from when using React with TypeScript?
public constructor(props: any) {
super(props);
this.state = {
userName:"Code to html, one way -->",
password:""
};
}
We are not importing it in the super() call, so where does it comes from?
It comes from the internal implementation of React component which you inherit by extending the class React.Component:
class MyComponent from React.Component {
// this.setState, this.state,
// lifecycle methods and more
}
See React.Component and its instance properties.
where does it comes from?
It comes from the constructor. The line you are asking about is exactly where this.state is initialized.

React - constructor function [duplicate]

This question already has answers here:
Is it better to define state in constructor or using property initializers?
(3 answers)
Closed 3 years ago.
I'm trying to learn react.
The documentation for react says to pass constructor arguments as follows.
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
render() {
This post says the reason to reference super in that function is you might need to have props in super() if you want to access this.props in the constructor.
But - if you don't need to do that, and you just need to initialise state, do you still need the super() line?
I have seen a lot of tutorials that define it as follows:
class Basic extends React.Component {
state = {
selectedValue: null,
createdAt: null
};
I can't find a reference to why this is acceptable. Do you need super, even if you don't need props in the constructor?
The snippet uses class fields proposal.
class Comp extends React.Component {
this.state = {...};
...
}
is syntactic sugar for
class Comp extends React.Component {
constructor(props) {
super(props);
this.state = {...};
}
}
In case a class doesn't need explicit constructor, constructor can be omitted. In case it needed explicit constructor, it should contain super(props) because it's required to properly inherit from React.Component.
This requirement doesn't related with React it's related with new ECMAScript 2015 Classes.
Look the Inheritance syntax section at this mozilla article;
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance#Inheritance_with_class_syntax
When you create a new react component you need inherit from React.Component class. So if you need to define a constructor for your class you need call super otherwise don't need it.

Do the constructors of React Components need the props argument?

Should I include the props argument in the constructor and call to super if I am not using props at all for a component?
For example, if I write:
class NotePage extends React.Component<void, State> {
constructor(){
super();
this.state = {
filterStr: "string"
};
}
...
}
Will this cause any issues?
I'm asking because if I include props then flow complains about a missing annotation and one way to solve the problem is to remove the props argument.
From official docs React Constructor
you should call super(props) before any other statement. Otherwise, this.props will be undefined in the constructor, which can lead to bugs
constructor(props) {
// no super call
}
If you don't call it, the data passed from parent as properties is not available inside child component's constructor with props. Props will, however, still be available in the rest of the component, such as the render function.
e.g.
class Parent extends React.Component{
render(){
return (<Child mydata = {'some data here'}/>)
}
}
class Child extends React.Component{
constructor(){
super(); //no props
this.props.mydata //will be undefined
}
render(){
this.props.mydata //defined
}
}
First of all you don't need constructor function at all, when you are not accessing props in initialization of component. You can write your state this way:
class NotePage extends React.Component<void, State> {
state = {
filterStr: "string"
}
...
}
Only when you are using props for initialization you need to , make use of constructor and call this way:
class NotePage extends React.Component<void, State> {
constructor(props){
super(props);
this.state = {
filterStr: "string"
};
}
...
}
Hope this helps !!
I found a great link written by #dan Abramov (react core team). this also might help people understanding super(props). Link

What is the difference between using constructor vs getInitialState in React / React Native?

I've seen both used interchangeably.
What are the main use cases for both? Are there advantages / disadvantages? Is one a better practice?
The two approaches are not interchangeable. You should initialize state in the constructor when using ES6 classes, and define the getInitialState method when using React.createClass.
See the official React doc on the subject of ES6 classes.
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { /* initial state */ };
}
}
is equivalent to
var MyComponent = React.createClass({
getInitialState() {
return { /* initial state */ };
},
});
The difference between constructor and getInitialState is the difference between ES6 and ES5 itself.
getInitialState is used with React.createClass and
constructor is used with React.Component.
Hence the question boils down to advantages/disadvantages of using ES6 or ES5.
Let's look at the difference in code
ES5
var TodoApp = React.createClass({
propTypes: {
title: PropTypes.string.isRequired
},
getInitialState () {
return {
items: []
};
}
});
ES6
class TodoApp extends React.Component {
constructor () {
super()
this.state = {
items: []
}
}
};
There is an interesting reddit thread regarding this.
React community is moving closer to ES6. Also it is considered as the best practice.
There are some differences between React.createClass and React.Component. For instance, how this is handled in these cases. Read more about such differences in this blogpost and facebook's content on autobinding
constructor can also be used to handle such situations. To bind methods to a component instance, it can be pre-bonded in the constructor. This is a good material to do such cool stuff.
Some more good material on best practices
Best Practices for Component State in React.js
Converting React project from ES5 to ES6
Update: April 9, 2019,:
With the new changes in Javascript class API, you don't need a constructor.
You could do
class TodoApp extends React.Component {
this.state = {items: []}
};
This will still get transpiled to constructor format, but you won't have to worry about it. you can use this format that is more readable.
With React Hooks
From React version 16.8, there's a new API Called hooks.
Now, you don't even need a class component to have a state. It can even be done in a functional component.
import React, { useState } from 'react';
function TodoApp () {
const items = useState([]);
Note that the initial state is passed as an argument to useState; useState([])
Read more about react hooks from the official docs
OK, the big difference is start from where they are coming from, so constructor is the constructor of your class in JavaScript, on the other side, getInitialState is part of the lifecycle of React.
constructor is where your class get initialised...
Constructor
The constructor method is a special method for creating and
initializing an object created with a class. There can only be one
special method with the name "constructor" in a class. A SyntaxError
will be thrown if the class contains more than one occurrence of a
constructor method.
A constructor can use the super keyword to call the constructor of a
parent class.
In the React v16 document, they didn't mentioned any preference, but you need to getInitialState if you using createReactClass()...
Setting the Initial State
In ES6 classes, you can define the initial state by assigning
this.state in the constructor:
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {count: props.initialCount};
}
// ...
}
With createReactClass(), you have to provide a separate
getInitialState method that returns the initial state:
var Counter = createReactClass({
getInitialState: function() {
return {count: this.props.initialCount};
},
// ...
});
Visit here for more information.
Also created the image below to show few lifecycles of React Compoenents:
If you are writing React-Native class with ES6, following format will be followed. It includes life cycle methods of RN for the class making network calls.
import React, {Component} from 'react';
import {
AppRegistry, StyleSheet, View, Text, Image
ToastAndroid
} from 'react-native';
import * as Progress from 'react-native-progress';
export default class RNClass extends Component{
constructor(props){
super(props);
this.state= {
uri: this.props.uri,
loading:false
}
}
renderLoadingView(){
return(
<View style={{justifyContent:'center',alignItems:'center',flex:1}}>
<Progress.Circle size={30} indeterminate={true} />
<Text>
Loading Data...
</Text>
</View>
);
}
renderLoadedView(){
return(
<View>
</View>
);
}
fetchData(){
fetch(this.state.uri)
.then((response) => response.json())
.then((result)=>{
})
.done();
this.setState({
loading:true
});
this.renderLoadedView();
}
componentDidMount(){
this.fetchData();
}
render(){
if(!this.state.loading){
return(
this.renderLoadingView()
);
}
else{
return(
this.renderLoadedView()
);
}
}
}
var style = StyleSheet.create({
});
These days we don't have to call the constructor inside the component - we can directly call state={something:""}, otherwise previously first we have do declare constructor with super() to inherit every thing from React.Component class
then inside constructor we initialize our state.
If using React.createClass then define initialize state with the getInitialState method.
The big difference is start from where they are coming from, so constructor is the constructor of your class in JavaScript, on the other side, getInitialState is part of the lifecycle of React . The constructor method is a special method for creating and initializing an object created with a class.
If someone is still looking for answer then this link will be helpful
Link
The constructor and getInitialState both in React are used to
initialise state, but they can't be used interchangeably.
We use getInitialState with React.createClass and constructor is used
with React.Component.
The constructor is the ideal place to set up your component's initial state. Instead of using setState() in other methods, you will need to assign the initial state directly.
class Hello extends React.Component {
constructor(props) {
super(props);
this.setState({
title: 'This is the first test'
});
}
render() {
return <div>{this.state.title} </div>
}
}
ReactDOM.render(<Hello />, document.getElementById('container'));
The main fundamental difference between ES5 and ES6 is in the new
class keyword. ES5 didn't provide the convenience of defining the
React component as classes however ES did provide the convenience to
define react component as class.
and more simple is that getInitialState is the ES5 friendly method to
define the initial state of a React component. We use getInitialState
with React.createClass and constructor is used with React.Component
Example:
class Goodmorning extends React.Component {
render() {
return <span>Good Morning</span>;
}
}
It would rely on helper module called create-react-class:
var createGoodmorningReactClass = require('create-react-class');
var Goodmorning = createReactClass({
render: function() {
return <span>Good Morning</span>;
}
});
The object passed into create-react-class that is defined in initial stage by calling the getInitialState attribute:
var Goodmorning = createReactClass({
getInitialState: function() {
return {name: this.props.name};
},
render: function() {
return <span>Good {this.state.name}</span>;
}
});
In ES6 implementation:
class Goodmorning extends React.Component {
constructor(props) {
super(props);
this.state = {
name: props.name
}
}
render() {
return <span>Good {this.state.name}</span>;
}
}
and also read this article if someone is still looking for an answer.
Link
In constructor we should always initialize the state.

Resources