How to properly deal with global states in ReactJS?

Let’s say I am creating a bookstore and I want to add, delete, update, etc, books to my list (basically, manipulate the books list).
I am creating a global state with the context API and functions like bellow:

//defining my global state
const [books, setBooks] = useState([ ])

// defining a function to manipulate the global state
const addBook = (newBook) => {
let newBooksList = [newBook, …books]

And then I pass those functions to the components that needed it.
Is this the right approach? I mean, I know that it works but is this considered good practice or there are other better ways to do those types of things?

Yeah, it’ll work fine for a while as a quick prototype. There are a number of reasons why this isn’t a good idea though.

Primarily, that’s not a useful place to store the data. That list of books is not really state per se, it’s the data the app depends on.

Values that live in global state would [for example] normally be able to tell me “am I logged in?” or “what are my current user settings?”. They’re things that have to be available to the entire application, but they’re local to the app and they’re often volatile.

So in this theoretical example you have, the data should absolutely not be stored in memory local to the app. If you refresh the app, everything it depends on is now gone. It can’t fulfil its primary function (be a bookstore), because the data is local to a single client, and the user of that client needs to populate the entire store every time they use the app.

You can pull the data from somewhere else (a JSON file, a database etc) when the state container is initialised, but it’s much easier to just make calls against an API (naturally, the complication is then the API, which I am glossing over). Then you don’t have global state, and you can make calls from the components themselves, and you don’t have to duplicate logic from the server to the client, and you don’t have the nightmare of keeping two sets of data in two different places in sync.

React is a UI library. It is for rendering an interface, don’t lose sight of that. It’s not a web framework, and it’s not a database.

Secondly, there are [many] situations where you do want to put the data into state, so understanding how to do what you’re outlining is an important thing – do carry on with this. But you’ve chosen a very inefficient way to do it. Because that data effectively is the app it is likely that everything is going to rerender every time you make a change to that array: you’re building an entirely new set of data every single time you make any change. As that array gets bigger, you’re going to hit performance problems fairly quickly.

I would recommend that if you’re going to have lots of complex data you need to manipulate, and that data lives on the client in a state container, use something that has very strict rules about how to access and update that data and follow the recommended patterns. ie just use Redux, rather than an ad-hoc version of the same thing.

Finally, note that if you use global variables, things tend to be easy when the system is small and simple. Systems normally develop to stop being small and simple very quickly, and global variables then generally end up being a source of bugs. Global variables for state exacerbate this issue tenfold. They very often have to exist, but you should try to limit their usage as much as possible