Four ways to initialize a React component'sΒ state
In React, state
is a special property of a components class. Whenever the state
is modified, the component re-renders.
There are 4 different way's to initialize a React component's state. They fundamentally all achieve the same thing but have differences between them.
Initialize state in the constructor
import React from "react";
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
text: "hello",
};
}
updateText = (e) => this.setState({text: e.target.value});
render() {
return <input value={this.state.text} onChange={this.updateText} />;
}
}
This is probably the most popular way to initialize a component's state. However, it's not always the best as it does require the most code to achieve. You should only use this method if you need to perform other initialization steps in the constructor.
Initialize state as a class property
import React from "react";
class MyComponent extends React.Component {
state = {
text: "hello",
};
updateText = (e) => this.setState({text: e.target.value});
render() {
return <input value={this.state.text} onChange={this.updateText} />;
}
}
This method is slowly gaining popularity due to it being easier to write. Also, not needing to define a constructor means no forgetting to call super(props)
. Keep in mind, you can still access this.props.
when defining state this way.
Using React hooks
import React from "react";
function MyComponent() {
const [text, setText] = React.useState("hello");
return <input value={text} onChange={(e) => setText(e.target.value)} />;
}
While this is not state in the traditional sense, React hooks is slowly becoming a great replacement for how we would usually work with component state. It requires significantly less boilerplate code and is much easier to reason with.
Initializing state with React.createClass
import React from "react";
const MyComponent = React.createClass({
getInitialState: () => {
return {text: "hello"};
},
updateText: (e) => this.setState({text: e.target.value}),
render: () => {
return <input value={this.state.text} onChange={this.updateText} />;
},
});
If you are unable to use the JSX syntax for writing React components, you will need to declare state using the getInitialState
property with React.createClass
;
The correct way to use state
State is important but it's also easy to misuse. When building React applications, it's best to separate the business logic from the UI.
We want our UI components to be "dumb". Meaning they take a certain input and produce a certain output. They shouldn't do anything fancy internally that we might lose track of.
For example, let's say you are building a simple application which allows a user to type their name into an input field. You might think it's best to write it like this.
import React from "react";
import ReactDOM from "react-dom";
function MyApp() {
const [name, setName] = React.useState("Your name");
return <input value={name} onChange={(e) => setName(e.target.value)} />;
}
const root = document.getElementById("root");
ReactDOM.render(<MyApp />, root);
This is all fine and dandy to start with. However, once you start expanding on it, say you now need 2 more input fields, everything will start to get messy.
import React from "react";
import ReactDOM from "react-dom";
function MyApp() {
const [name, setName] = React.useState("Your name");
const [age, setAge] = React.useState("Your age");
const [country, setCountry] = React.useState("Your country");
return (
<div>
<input value={name} onChange={(e) => setName(e.target.value)} />
<input value={age} onChange={(e) => setAge(e.target.value)} />
<input value={country} onChange={(e) => setCountry(e.target.value)} />
</div>
);
}
const root = document.getElementById("root");
ReactDOM.render(<MyApp />, root);
In this instance, we can clean up this code significantly by separating the input fields into their own component.
import React from "react";
import ReactDOM from "react-dom";
function Input(props) {
return (
<input
value={props.value}
onChange={(e) => props.onChange(e.target.value)}
/>
);
}
function MyApp() {
const [name, setName] = React.useState("Your name");
const [age, setAge] = React.useState("Your age");
const [country, setCountry] = React.useState("Your country");
return (
<div>
<Input value={name} onChange={setName} />
<Input value={age} onChange={setAge} />
<Input value={country} onChange={setCountry} />
</div>
);
}
const root = document.getElementById("root");
ReactDOM.render(<MyApp />, root);
This is far easier to maintain and reason with as we have split the component managing the state from the UI components which just render the props they are given.
Comments