Is the call to super(props) in an ES6 class important? - reactjs

Suppose I've the following class:
class Tabs extends React.Component {
displayName: Tabs;
static propTypes = {
selected: React.PropTypes.number,
children: React.PropTypes.oneOfType([
React.PropTypes.array,
React.PropTypes.element
]).isRequired
};
constructor() {
super();
this.state = {
selected: 0,
maxSelected: 0
};
render() {
return(
<div>
{this.props.selected}
{this.props.children}
</div>
);
}
};
I want to know that if passing the following constructor is important:
constructor(props) {
super(props);
}
My current code works just fine but I wanted to know if this is a good practice.

According to Sophie Alpert with the React team it's only necessary to pass props into the constructor if you intend on using this.props inside the constructor. After the constructor is invoked, React attaches the props to the component from the outside.

Related

React: How to read state from within handler function?

I'm new to React working on an existing React component (that appears to be built in an older style - no hooks).
I want to read and set state within a handler function. I have the following code:
export default class MyComponent extends React.Component {
static defaultProps = {
data: {}
};
constructor(props) {
super(props);
// Other states
this.state.myState = false;
};
handleMyChange() {
if (!this.state.myState) {
console.log("hello world");
}
}
However I get the error Cannot read properties of undefined.
I've tried various like state.myState but am not really sure what I should be doing.
Can anyone point me in the right direction?
In order to have this context in your function, you will need to bind it in the constructor first
Here is a small example is taken from the official doc:
import React from "react";
export default class SayHello extends React.Component {
constructor(props) {
super(props);
this.state = { message: "Hello!" };
// This line is important!
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
alert(this.state.message);
}
render() {
// Because `this.handleClick` is bound, we can use it as an event handler.
return <button onClick={this.handleClick}>Say hello</button>;
}
}

What is the diffrence between the following ways of initalizing the state [duplicate]

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.

how to pass just the function from one component to other component without passing the whole component or button click

I am new to react and in a bit of a problem . I have a component, component1. which has a function.
class ReportModal extends React.Component {
constructor(props) {
super(props);
this.state = {
modal: false,
imagesList: [],
code: []
};
this.toggle = this.toggle.bind(this);
}
toggle() {
this.setState({
modal: !this.state.modal
});
}
render() {
return(
<component1/>
)
}
I want to pass the toggle function in another component, component2
class Report extends React.Component {
constructor(props) {
super(props);
this.state = {
modal: false
};
}
render() {
return(
<component2/>
)
}
How do I pass just the toggle function from one component to another without passing the whole component or using a click event
You will have to firstly set the hierarchy of your components such as parent, sibling or child component. You can pass information from parent to child component through props.
Reverse flow occurs as a callback function.
If you want to call a function from parent component, create a function inside it and pass function as props.
class ReportModal extends React.Component {
constructor(props) {
super(props);
this.state = {
modal: false,
imagesList: [],
code: []
};
this.toggle = this.toggle.bind(this);
}
toggle(modal) {
this.setState({
modal: modal
});
}
render() {
return(
<component2 mod={this.toggle}/>
)
}
The child component will call this function on the occurrence of event and provide child data.
class Component2 extends React.Component {
constructor(props) {
super(props);
this.handleClick=this.handleClick.bind(this);
}
handleClick(){
this.props.mod(true)
}
render(){
return (
<button onClick={this.handleClick}></button>
)}
}

Reactjs, typescript unable to set initial state inside component

I'm very new to React. I have a component that renders fine, when I try to initialise the state, it says It cannot find the name, as I have not declared it yet, so how do I initialise it properly? I'm using:
"react": "^15.5.4",
"react-dom": "^15.5.4",
The component errors here on the line below:
export class Profile extends React.Component<{}, state> {
constructor(props){
super(props);
this.state = [{name: 'baz'}, {name: 'shaz'}];
}
public render() {
return (
<section>
<section>
<h3>profile 1</h3>
<div>baz</div>
</section>
<section>
<h3>profile 2</h3>
<div>shaz</div>
</section>
</section>
)
}
ReactDOM.render(
>> this is where I call <Profile />,
document.getElementById('app'),
)
Edit
So I managed to solve the issue with everyones help:
interface State {
name: string;
}
export class Profile extends React.Component<{}, State> {
public state: State;
constructor(props){
super(props);
this.state = {
name: 'baz111'
};
}
public render() {
return (
<section>
<section>
<h3>profile 1</h3>
<div>baz</div>
</section>
<section>
<h3>profile 2</h3>
<div>{this.state.name}</div>
</section>
</section>
)
}
}
this.state is just an object. In this scenario you can run a loop on this.state object to get the value of each name, or if you want you can set all the name under another parent object, for example: let say you want to store names under users key. That would be,
constructor(props){
super(props);
this.state = {
users: [
{name: 'baz'}, {name: 'shaz'}
]
};
}
Now you should loop on this.state.users to get the name values.
Example,
// Loop using es6 map
componentWillMount() {
this.state.users.map( user => {
console.log( user.name )
} )
}
As people said already, this.state has to be an object.
I think the real problem is when you initialize your component.
export class Profile extends React.Component<{}, state>
You see that state? That's the default state! As you didn't declare it, that's undefined. Please remove it or set it as void. Or, you can define it outside of your component:
1 - First alternative
export class Profile extends React.Component<{}, void> {
constructor(props) {
super(props)
this.state = {
users: [/* what you need */]
}
}
}
2 - Second alternative
type state {
{
users: [/* what you need */]
}
}
export class Profile extends React.Component<{}, state> {
constructor(props) {
super(props)
}
}
State is an Object.
Write it like this to define the data in state:
this.state = {
data: [
{name: 'baz'},
{name: 'shaz'}
]
}
Then access the state values by this.state.data.
Update:
Data is an array so you need to use map to print all the values, if you want to print specific value then access that by using the index of that item:
this.state.data[0].name ---> baz
this.state.data[1].name ---> shaz
By using map:
this.state.data.map(el => {
console.log('name', el.name);
})

Warning: getInitialState was defined on DimensionPicker, a plain JavaScript class. This is only supported for classes created using React.createClass

I am trying to write my first react control. Here is what I have written
import React from 'react';
import DimensionPickerAction from '../actions/DimensionPickerActions.js';
import MovieLensAppStore from '../stores/MovieLensAppStore.js';
class DimensionPicker extends React.Component {
constructor(props) {
super(props);
this.state = { items: [], currentItem: '' };
}
getInitialState() {
this.state = {
items: MovieLensAppStore.getAttributes(this.props.dimension),
currentItem : MovieLensAppStore.getCurrentAttribute(this.props.dimension)
};
}
onSelectionChange(newValue) {
DimensionPickerAction.selectionChange(this.props.dimension, newValue);
}
render() {
var optionNodes = this.state.items.map((item) => {
if (item === this.state.currentItem)
return(<option value="{item}" selected>{item}</option>)
else
return(<option value="{item}">{item}</option>)
});
return(<div><select onchange="onSelectionChange">{optionNodes}</select></div>);
}
}
export default DimensionPicker;
Very surprisingly, I get an error
Warning: getInitialState was defined on DimensionPicker, a plain JavaScript
class. This is only supported for classes created using React.createClass. Did
you mean to define a state property instead?
I find this very confusing because clearly my component derives from React.Component
Eric's comment is correct. You're using ES6 classes, which means that getInitialState is not supported. You'll need to change this:
class DimensionPicker extends React.Component {
constructor(props) {
super(props);
this.state = { items: [], currentItem: '' };
}
getInitialState() {
this.state = {
items: MovieLensAppStore.getAttributes(this.props.dimension),
currentItem : MovieLensAppStore.getCurrentAttribute(this.props.dimension)
};
}
to this:
class DimensionPicker extends React.Component {
constructor(props) {
super(props);
this.state = {
items: MovieLensAppStore.getAttributes(props.dimension),
currentItem : MovieLensAppStore.getCurrentAttribute(props.dimension)
};
}
What about this, if you like to save the initial state construction somewhere for later use:
class DimensionPicker extends React.Component {
constructor(props) {
super(props);
this._getInitialState = this._getInitialState.bind(this)
this.state = this._getInitialState();
}
_getInitialState() {
return { items: [], currentItem: '' }
}

Resources