this.state vs state in React - javascript

I'm working in a new codebase. Normally, I would set up state like this in a React component:
class App extends React.Component {
constructor() {
super();
this.state={
foo: 'bar'
}
}
....
In this new codebase, I'm seeing a lot of this:
class App extends React.Component {
state={
foo: 'bar'
}
....
Is there an advantage to doing it this way? They seem to only do it when state doesn't need to be altered. I always thought of state as being something React handled. Is this an ok thing to do?

The end result of both approaches is the same. Both approaches are just setting the initial state of the component. It's worth noting that class properties are a stage 3 proposal, so all development environments may not be able to use them.
I personally like to use the class field variant if nothing else is done in the constructor, as it is less code to write, and you have no super call to worry about.
Example
class Component1 extends React.Component {
state = { value: this.props.initialValue };
render() {
return <div> {this.state.value} </div>
}
}
class Component2 extends React.Component {
constructor(props) {
super(props);
this.state = { value: props.initialValue };
}
render() {
return <div> {this.state.value} </div>
}
}
function App() {
return (
<div>
<Component1 initialValue={1} />
<Component2 initialValue={2} />
</div>
);
}

Actually both of them bind to this pointer. the this that made in constructor of class.
Totally you can access to local state by this.state but in first style you can pass props to constructor by super and then use it in state declaration, just like below:
class App extends React.Component {
constructor(props) {
super(props);
this.state={
foo: 'bar',
jaz: props.someParentState,
}
}
....
Awesome, you can access to props in constructor, isn't pretty? I definitely use this style for local state declaration.
Hope this helps you.

Related

How to pass variables from class to class

Alright, so I'm trying to simplify a project I'm working on, but of all the information I've read on the internet, none of it has answered my question. My doubt is how can I pass variables (the name of the variable, and its value) from one class to another class? Should I use props? Should I just do something similar to this.state.variable? How can it be done? I'll write a sample code just to show what I'm trying to do more visually, however, this is not my actual code. Thanks for helping :)
class FishInSea{
constructor(props){
super(props);
this.setState({fishInSea: 100});
}
render(){
return(
<div>Fish in the sea: {this.state.fishInSea}</div>
);
}
}
class FishInOcean{
constructor(props){
super(props);
this.setState({fishInOcean: <FishInSea this.props.fishInSea/> * 1000});
}
render(){
return(
<div>Fish in the ocean: {this.state.fishInOcean}</div>
);
}
}
export default FishInOcean;
You need to first make both the classes in to React components. Since both the classes modify the state so they called as statefull components. The class has to extend the Base class of React i.e., Component.
in constructor we only do state initialisations but won’t modify the state there. But you are modifying the state which isn’t correct. Instead move setState to componentDidMount.
Say suppose in FishInSea class you have fishInSea and you want to pass it to FishInOcean component as props.
Check below two corrected components how they are passed from one component to the other
import React, { Component } from “react”;
class FishInSea extends Component{
constructor(props){
super(props);
this.state = {
fishInSea: 100
}
}
componentDidMount(){
this.setState({fishInSea: 100});
}
render(){
const { fishInSea } = this.state;
return(
<div>Fish in the sea:
<FishInOcean fishInSea={fishInSea} />
</div>
);
}
}
import React, { Component } from “react”;
class FishInOcean extends Component{
constructor(props){
super(props);
this.state = {fishInOcean: 1000}
}
componentDidMount(){
this.setState({fishInOcean: 1000});
}
render(){
const { fishInOcean} = this.state;
const { fishInSea } = this.props;
return(
<div>Fish in the ocean: {fishInOcean}
{fishInSea}
</div>
);
}
}
export default FishInOcean;
/*There was a typo*/

React component initialize state from props

In React, are there any real differences between these two implementations?
Some friends tell me that the FirstComponent is the pattern, but I don't see why. The SecondComponent seems simpler because the render is called only once.
First:
import React, { PropTypes } from 'react'
class FirstComponent extends React.Component {
state = {
description: ''
}
componentDidMount() {
const { description} = this.props;
this.setState({ description });
}
render () {
const {state: { description }} = this;
return (
<input type="text" value={description} />
);
}
}
export default FirstComponent;
Second:
import React, { PropTypes } from 'react'
class SecondComponent extends React.Component {
state = {
description: ''
}
constructor (props) => {
const { description } = props;
this.state = {description};
}
render () {
const {state: { description }} = this;
return (
<input type="text" value={description} />
);
}
}
export default SecondComponent;
Update:
I changed setState() to this.state = {} (thanks joews), However, I still don't see the difference. Is one better than other?
It should be noted that it is an anti-pattern to copy properties that never change to the state (just access .props directly in that case). If you have a state variable that will change eventually but starts with a value from .props, you don't even need a constructor call - these local variables are initialized after a call to the parent's constructor:
class FirstComponent extends React.Component {
state = {
x: this.props.initialX,
// You can even call functions and class methods:
y: this.someMethod(this.props.initialY),
};
}
This is a shorthand equivalent to the answer from #joews below. It seems to only work on more recent versions of es6 transpilers, I have had issues with it on some webpack setups. If this doesn't work for you, you can try adding the babel plugin babel-plugin-transform-class-properties, or you can use the non-shorthand version by #joews below.
You don't need to call setState in a Component's constructor - it's idiomatic to set this.state directly:
class FirstComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
x: props.initialX
};
}
// ...
}
See React docs - Adding Local State to a Class.
There is no advantage to the first method you describe. It will result in a second update immediately before mounting the component for the first time.
Update for React 16.3 alpha introduced static getDerivedStateFromProps(nextProps, prevState) (docs) as a replacement for componentWillReceiveProps.
getDerivedStateFromProps is invoked after a component is instantiated as well as when it receives new props. It should return an object to update state, or null to indicate that the new props do not require any state updates.
Note that if a parent component causes your component to re-render, this method will be called even if props have not changed. You may want to compare new and previous values if you only want to handle changes.
https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops
It is static, therefore it does not have direct access to this (however it does have access to prevState, which could store things normally attached to this e.g. refs)
edited to reflect #nerfologist's correction in comments
You could use the short form like below if you want to add all props to state and retain the same names.
constructor(props) {
super(props);
this.state = {
...props
}
//...
}
YOU HAVE TO BE CAREFUL when you initialize state from props in constructor. Even if props changed to new one, the state wouldn't be changed because mount never happen again.
So getDerivedStateFromProps exists for that.
class FirstComponent extends React.Component {
state = {
description: ""
};
static getDerivedStateFromProps(nextProps, prevState) {
if (prevState.description !== nextProps.description) {
return { description: nextProps.description };
}
return null;
}
render() {
const {state: {description}} = this;
return (
<input type="text" value={description} />
);
}
}
Or use key props as a trigger to initialize:
class SecondComponent extends React.Component {
state = {
// initialize using props
};
}
<SecondComponent key={something} ... />
In the code above, if something changed, then SecondComponent will re-mount as a new instance and state will be initialized by props.
set the state data inside constructor like this
constructor(props) {
super(props);
this.state = {
productdatail: this.props.productdetailProps
};
}
it will not going to work if u set in side componentDidMount() method through props.
If you directly init state from props, it will shows warning in React 16.5 (5th September 2018)
you could use key value to reset state when need, pass props to state it's not a good practice , because you have uncontrolled and controlled component in one place. Data should be in one place handled
read this
https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#recommendation-fully-uncontrolled-component-with-a-key
You can use componentWillReceiveProps.
constructor(props) {
super(props);
this.state = {
productdatail: ''
};
}
componentWillReceiveProps(nextProps){
this.setState({ productdatail: nextProps.productdetailProps })
}

Add methods to Higher Order Components in React

From what I understand, HOCs in ReactJS add props to your decorated component, but I want to add methods that can also act on the state.
As an example, I generally never call this.setState() without checking this.isMounted() first. In essence, I want:
export default ComposedComponent => class BaseComponent extends React.Component {
static displayName = "BaseComponent";
constructor(props) {
super(props);
}
//------> I want this method to be available to any ComposedComponent
//------> And it has to act upon the state of ComposedComponent
updateState(obj) {
if (this.isMounted() && obj) {
this.setState(obj);
}
}
render() {
return (
<ComposedComponent {...this.props} {...this.state} />
)
}
}
Say I want to decorate my component Home. So I'd just return it as export default BaseComponent(Home).
But this.updateState() is not available inside Home class. How do I solve this?
Okay, I figured it out. I had spent too much time on this, so I hope this answer could help somebody out as well. Short answer: add the method in your decorator to props, then bind it in your decorated class' constructor.
Here is the code:
export default ComposedComponent => class BaseComponent extends React.Component {
static displayName = "BaseComponent";
constructor(props) {
super(props);
// Note how I am adding this to state
// This will be passed as a prop to your composed component
this.state = {
updateState: this.updateState
}
}
updateState(obj) {
this.setState(obj);
}
render() {
return (
<ComposedComponent {...this.props} {...this.state} />
)
}
}
And here is an example of a class that would use it (I'm using ES7 for simplicity):
#BaseComponent
class Home extends React.Component {
static displayeName = 'Home';
constructor(props) {
super(props);
// And here I am binding to it
this.updateState = this.props.updateState.bind(this);
}
render() {
return (
<div>Hi</div>
)
}
}

When making react components es6 syntax why is super initialised with props? [duplicate]

This question already has answers here:
What's the difference between "super()" and "super(props)" in React when using es6 classes?
(10 answers)
Closed 6 years ago.
I guess I'm not very good at JavaScript.
This is how I've seen react components initialised. The initial set state is done within the constructor.
export class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {count: props.initialCount};
}
why is there always a super(props). Is this required? Is calling super necessary at all? What would happen if super isn't called?
You need to pass props in super only if you want to access this.props in constructor of the class.
class Base extends React.Component {
constructor(props) {
console.log('Base', props);
}
render() {
return <div>Base {this.props.name}</div>;
}
}
class Sub extends Base {
constructor(props) {
super({
name: 'New name prop'
});
console.log('Sub', arguments);
}
}
var sub = <Sub name="Gomic" />
React.render(sub, document.getElementById('container'));
Props are by default not assigned in the constructor. They are assinged in the method React.createElement. So super(props) should be called only when the superclass's constructor manually assings props to this.props. When you just extend the React.Component calling super(props) method will do nothing with props.
Reference:
https://discuss.reactjs.org/t/should-we-include-the-props-parameter-to-class-constructors-when-declaring-components-using-es6-classes/2781/2

React constructor [duplicate]

When is it important to pass props to super(), and why?
class MyComponent extends React.Component {
constructor(props) {
super(); // or super(props) ?
}
}
There is only one reason when one needs to pass props to super():
When you want to access this.props in constructor.
Passing:
class MyComponent extends React.Component {
constructor(props) {
super(props)
console.log(this.props)
// -> { icon: 'home', … }
}
}
Not passing:
class MyComponent extends React.Component {
constructor(props) {
super()
console.log(this.props)
// -> undefined
// Props parameter is still available
console.log(props)
// -> { icon: 'home', … }
}
render() {
// No difference outside constructor
console.log(this.props)
// -> { icon: 'home', … }
}
}
Note that passing or not passing props to super has no effect on later uses of this.props outside constructor. That is render, shouldComponentUpdate, or event handlers always have access to it.
This is explicitly said in one Sophie Alpert's answer to a similar question.
The documentation—State and Lifecycle, Adding Local State to a Class, point 2—recommends:
Class components should always call the base constructor with props.
However, no reason is provided. We can speculate it is either because of subclassing or for future compatibility.
(Thanks #MattBrowne for the link)
In this example, you are extending the React.Component class, and per the ES2015 spec, a child class constructor cannot make use of this until super() has been called; also, ES2015 class constructors have to call super() if they are subclasses.
class MyComponent extends React.Component {
constructor() {
console.log(this); // Reference Error
}
render() {
return <div>Hello {this.props.name}</div>;
}
}
By contrast:
class MyComponent extends React.Component {
constructor() {
super();
console.log(this); // this logged to console
}
render() {
return <div>Hello {this.props.name}</div>;
}
}
More detail as per this excellent stack overflow answer
You may see examples of components created by extending the React.Component class that do not call super() but you'll notice these don't have a constructor, hence why it is not necessary.
class MyOtherComponent extends React.Component {
render() {
return <div>Hi {this.props.name}</div>;
}
}
One point of confusion I've seen from some developers I've spoken to is that the components that have no constructor and therefore do not call super() anywhere, still have this.props available in the render() method. Remember that this rule and this need to create a this binding for the constructor only applies to the constructor.
When you pass props to super, the props get assigned to this. Take a look at the following scenario:
constructor(props) {
super();
console.log(this.props) //undefined
}
How ever when you do :
constructor(props) {
super(props);
console.log(this.props) //props will get logged.
}
When implementing the constructor() function inside a React component, super() is a requirement. Keep in mind that your MyComponent component is extending or borrowing functionality from the React.Component base class.
This base class has a constructor() function of its own that has some code inside of it, to setup our React component for us.
When we define a constructor() function inside our MyComponent class, we are essentially, overriding or replacing the constructor() function that is inside the React.Component class, but we still need to ensure that all the setup code inside of this constructor() function still gets called.
So to ensure that the React.Component’s constructor() function gets called, we call super(props). super(props) is a reference to the parents constructor() function, that’s all it is.
We have to add super(props) every single time we define a constructor() function inside a class-based component.
If we don’t we will see an error saying that we have to call super(props).
The entire reason for defining this constructor() funciton is to initialize our state object.
So in order to initialize our state object, underneath the super call I am going to write:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
// React says we have to define render()
render() {
return <div>Hello world</div>;
}
};
So we have defined our constructor() method, initialized our state object by creating a JavaScript object, assigning a property or key/value pair to it, assigning the result of that to this.state. Now of course this is just an example here so I have not really assigned a key/value pair to the state object, its just an empty object.
Dan Abramov wrote an article on this topic:
Why Do We Write super(props)?
And the gist of it is that it's helpful to have a habit of passing it to avoid this scenario, that honestly, I don't see it unlikely to happen:
// Inside React
class Component {
constructor(props) {
this.props = props;
// ...
}
}
// Inside your code
class Button extends React.Component {
constructor(props) {
super(); // 😬 We forgot to pass props
console.log(props); // ✅ {}
console.log(this.props); // 😬 undefined
}
// ...
}
As per source code
function ReactComponent(props, context) {
this.props = props;
this.context = context;
}
you must pass props every time you have props and you don't put them into this.props manually.
super() is used to call the parent constructor.
super(props) would pass props to the parent constructor.
From your example, super(props) would call the React.Component constructor passing in props as the argument.
More information on super:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super
For react version 16.6.3, we use super(props) to initialize state element name : this.props.name
constructor(props){
super(props);
}
state = {
name:this.props.name
//otherwise not defined
};
Here we won't get this in the constructor so it will return undefined, but we will be able to fetch this outside the constructor function
class MyComponent extends React.Component {
constructor() {
console.log(this); // Reference Error i.e return undefined
}
render() {
return <div>Hello {this.props.name}</div>;
}
}
If we are using super(), then we can fetch the "this" variable inside the constructor as well
class MyComponent extends React.Component {
constructor() {
super();
console.log(this); // this logged to console
}
render() {
return <div>Hello {this.props.name}</div>;
}
}
So when we are using super(); we will be able to fetch this but this.props will be undefined in the constructor. But other than constructor, this.props will not return undefined.
If we use super(props), then we can use this.props value inside the constructor as well
Sophie Alpert's Answer
If you want to use this.props in the constructor, you need to pass
props to super. Otherwise, it doesn’t matter because React sets .props
on the instance from the outside immediately after calling the
constructor.
Here is the fiddle I've made:jsfiddle.net. It shows that props are assigned not in the constructor by default. As I understand they are assinged in the method React.createElement. Hence super(props) should be called only when the superclass's constructor manually assings props to this.props. If you just extend the React.Component calling super(props) will do nothing with props. Maybe It will be changed in the next versions of React.

Categories