You can think of state as the data your components need, and the ability your components have to update/access data that would need to be displayed by the component itself. Learning to use the state
object and setState
function will help you gain an understanding as to why we have React and what it’s really good at doing.
State and lifecycle explained in the React Docs
If we simply passed down some items to a component via props on an array for example, we wouldn’t really have a way for us to manipulate and update that information as needed.
React gives us a tool to work with the state
object that we put on our constructor function. This tool is called setState
and it lives on the Component
base-class as a method that we can tap into in order to make changes to state. Note calling setState will for React to trigger an invocation (call) to render
. This is how react is reactive. Any time we change our state, our component gets re-rendered and our changes are immediately reflected on the screen.
class App extends React.Component {
constructor() {
super();
this.state = {
[STATE_OBJECT]: ""
};
}
handleInputChange = (event) => {
this.setState({ [STATE_OBJECT]: event.target.value });
}
render() {
return (
<div>
<div>{this.state.[STATE_OBJECT]}</div>
<input
type="text"
placeholder="change the [STATE_OBJECT]"
onChange={this.handleInputChange}
/>
</div>
);
}
}
This input field is pretty trivial, and demonstrates the use of setState
pretty well, however, we’re trying to achieve the idea of reusability
. So lets take a look at what happens to our input handler if we bind it to our input in a controlled
fashion. One can create state from scratch.
class App extends React.Component {
constructor() {
super();
this.state = {
};
}
onClickMe = () => {
this.setState({message: "Clicked"})
}
render() {
return (
<div className="App">
<h1>Updating State via `SetState`</h1>
<p>{this.state.message}</p>
<button onClick={this.onClickMe}>Click me</button>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Changing the state of a boolean and conditionally rendering components is when things get interesting.
class LoginControl extends React.Component {
constructor(props) {
super(props);
this.state = {isLoggedIn: false};
}
handleLoginClick() {
this.setState({isLoggedIn: true});
}
handleLogoutClick() {
this.setState({isLoggedIn: false});
}
render() {
const isLoggedIn = this.state.isLoggedIn;
let button;
if (isLoggedIn) {
button = <LogoutButton onClick={this.handleLogoutClick} />;
} else {
button = <LoginButton onClick={this.handleLoginClick} />;
}
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
{button}
</div>
);
}
}
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
function LoginButton(props) {
return (
<button onClick={props.onClick}>
Login
</button>
);
}
function LogoutButton(props) {
return (
<button onClick={props.onClick}>
Logout
</button>
);
}