# Redux Concepts

## Redux Concepts - Action, Dispatch, Reducer & Store

Redux is based on 4 fundamental elements -

* **action** - An action is an object that represents an event (e.g. button click) or command that has occurred within an application. Action typically have a `type` and a `payload` property.
* **`dispatch()`** - `dispatch()` is a function that is used to send actions to the Redux store. It is the only way to trigger a state change in the store.
* **`reducer()`** -  Pure function that takes an `action` & a `state`as input, and return a **new state.** The reducer is responsible for updating the state of the application in response to actions.
* **store** - The store is an object that holds the entire state tree of your application. It notifys any subscribers that the state has changed.

## How Redux Store Works

Here's a simplified overview of how the Redux store works:

1. The store is created using the `createStore` function, which takes a `reducer()` function as its argument.
2. Components can dispatch actions to the store using the `dispatch()` function.
3. The `reducer()` function processes the action and returns a new state object.
4. The store updates its internal state to the new state object.
5. The store notifies any subscribers that the state has changed by calling their subscribed callback functions.
6. Components that are subscribed to the store can access the updated state using the `getState` function and re-render with the new state.

<figure><img src="https://109962327-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MC0Wq3Hv_Fc0WRkNF0M%2Fuploads%2FTN8gLf7YqcIC4Nc1NBcs%2FScreenshot%20(500).png?alt=media&#x26;token=f48f24e8-d03b-4564-8d04-04f2d3e7dafd" alt=""><figcaption><p>Redux Store Workflow</p></figcaption></figure>

## Redux Counter Application

Simple Redux app

{% tabs %}
{% tab title="App.js" %}

```jsx
// Get DOM elements for counter, increment, and decrement buttons
const counterElement = document.getElementById("counter");
const incrementElement = document.getElementById("increment");
const decrementElement = document.getElementById("decrement");

// Define initial state for the counter
const initialState = {
  value: 0,
};

// Define a reducer function for the counter that handles actions
const counterReducer = (state = initialState, action) => {
  // If the action is "increment", return a new state with the value incremented by 1
  if (action.type === "increment") {
    return {
      ...state, // Copy the existing state
      value: state.value + 1, // Update the value property
    };
  }
  // If the action is "decrement", return a new state with the value decremented by 1
  else if (action.type === "decrement") {
    return {
      ...state, // Copy the existing state
      value: state.value - 1, // Update the value property
    };
  }
  // If the action is not recognized, return the existing state
  else {
    return state;
  }
};

// Create a Redux store with the counter reducer
const store = Redux.createStore(counterReducer);
console.log(store); // Log the store to the console for debugging purposes

// Define a render function that updates the counter element with the current state
function render() {
  const state = store.getState(); // Get the current state from the store
  counterElement.innerText = state.value.toString(); // Update the counter element with the current value
}

render(); // Call the render function to update the counter element with the initial state

// Subscribe the render function to the store, so that it is called whenever the state changes
store.subscribe(render);

// Add event listeners to the increment and decrement buttons
incrementElement.addEventListener("click", () => {
  // Dispatch an "increment" action to the store
  store.dispatch({
    type: "increment",
  });
});

decrementElement.addEventListener("click", () => {
  // Dispatch a "decrement" action to the store
  store.dispatch({
    type: "decrement",
  });
});
c
```

{% endtab %}

{% tab title="index.html" %}

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Simple Counter Application</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script src="https://unpkg.com/redux@latest/dist/redux.min.js"></script>
  </head>
  <body>
    <div class="w-screen h-screen p-10 bg-gray-100 text-slate-700">
      <!-- header -->
      <h1 class="max-w-md mx-auto text-center text-2xl font-bold">
        Simple Counter Application
      </h1>

      <!-- counters -->
      <div class="max-w-md mx-auto mt-10 space-y-5">
        <div
          class="p-4 h-auto flex flex-col items-center justify-center space-y-5 bg-white rounded shadow"
        >
          <div id="counter" class="text-2xl font-semibold"></div>
          <div class="flex space-x-3">
            <button
              class="bg-indigo-400 text-white px-3 py-2 rounded shadow"
              id="increment"
            >
              Increment
            </button>
            <button
              class="bg-red-400 text-white px-3 py-2 rounded shadow"
              id="decrement"
            >
              Decrement
            </button>
          </div>
        </div>
      </div>
    </div>

    <script src="./script.js"></script>
  </body>
</html>

```

{% endtab %}
{% endtabs %}
