State is one of the biggest concepts to understand in frontend development when it comes to building single page applications.
In React, state is just data that changes over time. That could be inside a specific component — like a toggle or a counter — or in some kind of global context, like which user is logged in.
React tracks that state for you, and when it changes, React automatically re-renders the component to reflect the new data in the UI.
States in React
There are two types of state in React: component state and global state also called application state.
Component state is data that is local to a component. It is data that is only relevant to that component and does not need to be shared with other components. An example would be a modal component with a piece of state called isOpen . It would be a boolean value that determines whether the modal is open or not. No other component is concerned with whether the modal is open or not, so it is local to that component. An example of global state, also called global state, would be a user object that contains information about the currently logged in user isLoggedIn . This data is relevant to the entire application and needs to be shared with multiple components. React has a built in context API for managing global state but you can also use a 3rd-party library like Redux or Zustand. Global State & SSR
State managers are not as important with SSR (Server-Side Rendered) applications because the server is responsible for rendering the initial UI and delivering it to the client with the necessary data already embedded. This means:
There's less need to manage complex client-side state during the initial load. Data is often fetched and injected on the server, reducing the amount of logic that has to happen in the browser. In many SSR apps, URL-based routing and server responses determine what gets rendered, which can eliminate the need for global state tools like Redux or Zustand in many cases. Page transitions often re-trigger server-side logic, refreshing data rather than relying on long-lived in-browser state. However, client-side state is still important for things like:
User input (forms, modals) Temporary UI state (toggled sections, tabs, active elements) Real-time updates or client-only interactions So while you still use useState and possibly context or lightweight state tools, heavy client-side state management becomes less critical in many SSR workflows.
Hooks
A hook is a special function in React that lets you “hook into” built-in features like state, lifecycle methods, or context inside functional components.
Before hooks, features like state and lifecycle methods were only available in class components. But now, thanks to hooks, we can do everything with function components — which are simpler and more common today.
Hooks always start with the word “use” — like useState, useEffect, or useContext. Each one gives you access to a specific React feature.
useState là một hook để quản lý state của component.
We use array destructuring here. That means we're pulling out two values from what useState returns:
`value` is the current state. `setValue` is the function we call to update that state. This will update it in an immutable way instead of changing it directly. We also pass in what we want for a default value.
You can name them whatever makes sense for your data. For example:
Every time the button is clicked:
The `setCount` function is called with the new value. React re-renders the component. The new count value shows up in the UI. 📌 Important: You should never change state directly like count++ — always use the setter function (e.g. setCount(count + 1) ) so React can detect the change and trigger a re-render.
Rating App useState Example
View App State in React Dev Tools
More on useState
Using a Function For the Initial State
Another thing you can do aside from passing in an initial value is to pass in a function that returns the initial value. This is useful when the initial state is expensive to compute.
This will set an intitial value of `4` for `count` and it will also log `Setting count` to the console.
You can outout `{count}` in the JSX to see the value.
Passing a Function To The Setter
You can also pass a function to the setter.
So instead of using setRating or setCount, you can call a custom function and call these setter fn.
Doing what we did here where what we are setting the count to is based on the current count is not a good idea. This is because React batches state updates. If you do this, you might not get the expected result when you update the state multiple times in a row.
To avoid this, you can pass a function to the setter that takes the previous state as an argument. This way, you can be sure that you are always updating the state based on the latest state.
Conditional Rendering with State