The nuances of useState

Only Use it for Function Components!

You may employ useState (or any other React Hook) in a function component.

  • Don't call useState in class components.
  • Don't call useState from regular JavaScript functions.
  • Don't call useState from outside of a function component.

Moreover, do not call useState (or any React Hooks) inside loops, conditions, or nested functions.

Instead, always use Hooks at the top level of your React function, before any returns.

You can also employ React Hooks to build your own custom Hooks. However, we will not cover this topic.

Update State Based on Previous State

Similar to this.setState in class component, the "state updater function" returned from useState allows you to consume the previous state using a callback pattern as follows.

const incrementCount = () => {
  setState((count) => count + 1);
};

Using Multiple useState

In class components, the entire state lives in one (potentially large) object, this.state. However, with useState, you can use as many variables as you wish to hold the state in function components.

const [volume, setVolume] = useState(80); 
const [playlist, setPlaylist] = useState([]);
const [currSong, setSong] = useState(""); 
const [isPlaying, setPlaying] = useState(false);

Each useState can store one value, and the value can be any JavaScript type — a number, boolean, object, array, etc.

Using an Object as State

You can use an object as the state.

const [post, setPost] = useState({
  author: "",
  content: ""
});

Let's say we want to update content! Here is how the updateContent function might look like:

const updateContent = (updatedContent) => {
  setPost((post) => ({
    author: post.author,
    content: updatedContent
  }));
}

The state updater function (setPost, here) doesn't "merge" new values with old — it overwrites (replaces) the state with the new value. This is a departure from the way this.setState worked in classes.

Resources