This documentation serves as a practical reference for Redux concepts, designed for future project use and to assist anyone seeking clarity on state management in JavaScript applications.
Redux is a predictable state container for JavaScript apps, most commonly used with React. Imagine it as a centralized warehouse for all the data (the "state") your application needs. This makes it significantly easier to manage and access that data consistently from any component within your application.
At its heart, Redux operates on a simple, one-way data flow. This fundamental principle ensures predictability and makes debugging easier. The flow involves three main parts: the Store, Actions, and Reducers.
The Store is a single, immutable JavaScript object that holds the entire state of your application. It's the "single source of truth" for your application's data. You'll only ever have one Redux store in your application.
When you want to change the state, you can't modify it directly. Instead, you dispatch an Action. An action is a plain JavaScript object that describes what happened. Think of it as sending a formal request or a "memo" to the store, indicating an intent to change the state.
Example Action to add a movie:
{
"type": "movies/addMovie",
"payload": "Transformers"
}A Reducer is a pure function that receives the current state and an action. Its sole responsibility is to decide how to update the state based on that action and return a brand new state object. It's called a "reducer" because it takes all incoming actions and "reduces" them down to a single new state. Crucially, reducers must never mutate the original state directly; they must always return a new copy.
The entire process follows a clear cycle:
- An event happens in your UI (e.g., a button click, an API response).
- Your UI dispatches an Action describing the event.
- The Store passes the current
stateand theactionto a Reducer. - The Reducer computes and returns a brand new state object.
- The Store updates itself with this new state.
- Any UI components subscribed to the relevant parts of the state automatically re-render to reflect the changes.
This is better visualized in the official Redux data flow diagram:
This project demonstrates a simple movie management application, originally derived from a tutorial (YouTube Link). Its primary purpose is to illustrate state management across multiple components, where Redux (specifically Redux Toolkit) proves invaluable.
While the original tutorial utilized JavaScript, this implementation has been converted to TypeScript for enhanced type safety and adherence to modern industry standards. Additionally, the styling has been customized.
Here's a detailed, step-by-step breakdown of the data flow when a new movie is added:

- A user types a movie title, like "Transformers," into the
<input>field and clicks the "Add Movie" button. - The button's
onClick={handleAddMovie}event is triggered. - Inside
handleAddMovie, thedispatchfunction is called with theaddMovie()action creator (from your slice). The current value of the input (newMoviestate) is passed as the argument.// This function call initiates the Redux cycle dispatch(addMovie("Transformers"));
- The
addMovie("Transformers")action creator generates a plain JavaScript object. Redux Toolkit automatically combines thenamefrom your slice ("movies") with the reducer function name ("addMovie") to create the unique action type. - The dispatched action object looks like this:
{ "type": "movies/addMovie", "payload": "Transformers" } - This action object is then sent to the Redux store via
dispatch.
- The store receives the action. Its primary role is to pass the current application
stateand theactionto its main "root reducer." - Your
configureStoresetup defines how different parts of your global state are managed. For instance, it specifies that themoviesproperty in your global state is handled bymovieReducer.reducer: { movies: movieReducer, // <-- The store maps 'movies/...' actions to this reducer },
- The store, through its root reducer, inspects the action type (
'movies/addMovie') and intelligently forwards it to the appropriatemovieReducer.
- The
movieReducerfrom yourmovieSlicetakes over. It examines theaction.typeand executes the corresponding function defined in itsreducersobject. - The
addMoviefunction withinmovieSliceis executed:statehere refers only to the currentmoviesslice of the global state (e.g.,{ movies: [...] }), not the entire app state.actionis the action object from Step 2.
(Note: TheaddMovie: (state, action) => { // action.payload is "Transformers" const newMovie: Movie = { id: state.movies[state.movies.length - 1].id + 1, // this state.movies // is saying (state.movies).movies, state = (state.movies) in this scope title: action.payload // The movie title from the action } // Redux Toolkit's Immer allows "mutating" logic, // which safely produces an immutable new state. state.movies.push(newMovie); },
idgeneration has been updated toDate.now()for robust uniqueness, andnewMovieis pushed instead ofaction.payloadto ensure the correct object structure.)
- Redux Toolkit leverages a library called Immer behind the scenes. This powerful tool allows you to write state-updating logic that looks like it's directly "mutating" the state (e.g.,
state.movies.push(...)). Immer then safely translates these mutations into immutable updates, returning a brand new state object. - The
movieSlicereturns a new state object specifically for themoviesslice. - The root reducer then assembles this new slice with any other (unchanged) slices to form the complete, new global state object.
- The store is now updated and holds this new, final application state.
- Any React components in your application that are subscribed to the Redux store (typically using the
useSelectorhook to extract data like themovieslist) will be notified of the state change. useSelectorefficiently compares the new data with the previously selected data. If the data has changed, the component will automatically re-render to display the updated information, ensuring your UI always reflects the latest state.
To explore this application and see Redux in action:
- Clone the repository to your local machine.
- Navigate to the project directory in your terminal.
- Install dependencies:
npm install - Start the development server:
npm run dev
Feel free to experiment with and extend this project. Its core purpose is to inform and assist in understanding Redux, building upon the foundational concepts from the original tutorial.
