This is the beauty of React, it's reactive style, that essentially means your UI is always bound to your state.
In Backbone, you do not get this for free, as the problem is that two-way binding in Backbone requires manual re-renders (via jQuery) which are direct DOM manipulations. This is expensive, meaning, it is not performant as your DOM grows.
React solves the problem via it's virtual DOM, which keeps an optimized DOM engine in memory, batching expensive updates onto the real DOM.
This means you get the convenience of your UI always representing your state, which means your code can become more declarative (what you want), and less imperative (what you need to do in order to get it). The author calls this "magic," but as somebody who was a Backbone main turned React main, I call this "sanity."
Class component:
class Counter extends Component {
state = { age: 42 };
handleAgeChange = () => {
this.setState({ age: this.state.age + 1 });
};
render() {
return (
<>
<button onClick={this.handleAgeChange}>Increment age</button>
<p>You are {this.state.age}.</p>
</>
);
}
}
Functional component: function Counter() {
const [age, setAge] = useState(42);
const handleAgeChange = () => setAge(age + 1);
return (
<>
<button onClick={handleAgeChange}>Increment age</button>
<p>You are {age}.</p>
</>
);
} const handleAgeChange = setAge((prevAge) => prevAge + 1); const handleAgeChange = () => setAge((prevAge) => prevAge + 1);
https://react.dev/reference/react/useState#updating-state-ba...The callback version is really only needed if there's a risk of setAge being called multiple times between renders and you do actually want all the mutations, vs only wanting it based on what's currently rendered.
People do add state managers to store state outside the component tree, but a lot of components don't need that.