# What Are ActionTypes.INIT and ActionTypes.REPLACE in Redux? Internal Lifecycle Explained

> Learn how Redux uses ActionTypes INIT and REPLACE for store initialization and hot module replacement. Understand these internal lifecycle actions.

- Repository: [Redux/redux](https://github.com/reduxjs/redux)
- Tags: internals
- Published: 2026-03-05

---

**ActionTypes.INIT and ActionTypes.REPLACE are private, internally-generated action types used by Redux to initialize store state and handle hot module replacement, respectively.**

These reserved action types live in the `reduxjs/redux` repository and are never meant to be dispatched by application code. Instead, they power critical lifecycle moments: `ActionTypes.INIT` triggers initial state population when you call `createStore()`, while `ActionTypes.REPLACE` enables seamless reducer swapping during code splitting and hot reloading.

## What Are ActionTypes.INIT and ActionTypes.REPLACE?

Redux generates two unique string identifiers in [`src/utils/actionTypes.ts`](https://github.com/reduxjs/redux/blob/main/src/utils/actionTypes.ts) to prevent collisions with user-defined actions:

- **`@@redux/INIT${randomString()}`** – Signals store creation and initial state gathering
- **`@@redux/REPLACE${randomString()}`** – Signals that the root reducer has been swapped via `store.replaceReducer()`

Both strings receive a random suffix per library instance, ensuring uniqueness across multiple Redux builds on the same page.

### How These Action Types Are Generated

In [`src/utils/actionTypes.ts`](https://github.com/reduxjs/redux/blob/main/src/utils/actionTypes.ts), Redux constructs these constants using a `randomString()` helper:

```typescript
const ActionTypes = {
  INIT: `@@redux/INIT${/* #__PURE__ */ randomString()}`,
  REPLACE: `@@redux/REPLACE${/* #__PURE__ */ randomString()}`,
  PROBE_UNKNOWN_ACTION: () => `@@redux/PROBE_UNKNOWN_ACTION${randomString()}`
};

```

The `/* #__PURE__ */` annotation helps bundlers with tree-shaking, while the random suffix prevents accidental handling of these actions in user reducers.

## How ActionTypes.INIT Initializes Redux Store State

When you invoke `legacy_createStore` (or `createStore`), Redux immediately dispatches `ActionTypes.INIT` to populate the initial state tree. This happens in [`src/createStore.ts`](https://github.com/reduxjs/redux/blob/main/src/createStore.ts) at approximately line 395:

```typescript
// src/createStore.ts
dispatch({ type: ActionTypes.INIT } as A);

```

Each reducer in your application receives this action. If a reducer receives `state === undefined`, it must return its default initial value. This mechanism allows Redux to build the complete state tree without requiring you to manually pass a preloaded state object.

### combineReducers and INIT Validation

The `combineReducers` utility in [`src/combineReducers.ts`](https://github.com/reduxjs/redux/blob/main/src/combineReducers.ts) uses `ActionTypes.INIT` to validate reducer shape during store creation. In the `assertReducerShape` function (lines 66-84), Redux calls each child reducer with `undefined` and the `INIT` action:

```typescript
function assertReducerShape(reducers) {
  Object.keys(reducers).forEach(key => {
    const reducer = reducers[key];
    // Verify reducer returns defined state for INIT
    const initialState = reducer(undefined, { type: ActionTypes.INIT });
    // Verify reducer handles unknown actions safely
    reducer(undefined, { type: ActionTypes.PROBE_UNKNOWN_ACTION() });
  });
}

```

This ensures every slice reducer properly initializes when called with `undefined` and does not throw on unknown action types.

## How ActionTypes.REPLACE Enables Hot Module Replacement

When you call `store.replaceReducer(newReducer)`—commonly used in hot module replacement (HMR) scenarios—Redux swaps the internal root reducer reference and dispatches `ActionTypes.REPLACE`. This occurs in [`src/createStore.ts`](https://github.com/reduxjs/redux/blob/main/src/createStore.ts) at approximately lines 45-46:

```typescript
// src/createStore.ts (replaceReducer implementation)
dispatch({ type: ActionTypes.REPLACE } as A);

```

The `REPLACE` action signals to the new reducer tree that a replacement has occurred. Existing slice reducers that persist across the swap receive their previous state, while newly added slices receive `undefined` and initialize themselves. This allows state to survive code-splitting or hot-reloading events without full store recreation.

### Suppressing Warnings During Reducer Replacement

`combineReducers` specifically checks for `ActionTypes.REPLACE` to avoid false-positive "unexpected key" warnings. When reducers are replaced during HMR, the state shape might legitimately change. In [`src/combineReducers.ts`](https://github.com/reduxjs/redux/blob/main/src/combineReducers.ts), the utility skips validation when it detects the replace action:

```typescript
if (action && action.type === ActionTypes.REPLACE) {
  return; // Skip unexpected key checks during replacement
}

```

This ensures developers don't see spurious warnings when legitimately swapping reducer logic in development environments.

## Summary

- **ActionTypes.INIT** initializes the Redux store by dispatching during `createStore()`, forcing each reducer to return its default state when called with `undefined`.
- **ActionTypes.REPLACE** facilitates hot module replacement by signaling reducer swaps via `store.replaceReducer()`, allowing state persistence across code splits while suppressing validation warnings.
- Both action types are generated in [`src/utils/actionTypes.ts`](https://github.com/reduxjs/redux/blob/main/src/utils/actionTypes.ts) with random string suffixes to prevent collisions and are consumed in [`src/createStore.ts`](https://github.com/reduxjs/redux/blob/main/src/createStore.ts) and [`src/combineReducers.ts`](https://github.com/reduxjs/redux/blob/main/src/combineReducers.ts).
- These are **private implementation details**—never dispatch them manually or handle them explicitly in your reducers.

## Frequently Asked Questions

### Can I dispatch ActionTypes.INIT or ActionTypes.REPLACE manually?

No. These action types are reserved for internal Redux use only. Dispatching them manually could break state initialization logic or trigger unexpected behavior during reducer replacement. The Redux source code explicitly warns: "Do not reference these action types directly in your code."

### Why do these action types have random strings appended?

The random suffixes (generated by `randomString()` in [`src/utils/actionTypes.ts`](https://github.com/reduxjs/redux/blob/main/src/utils/actionTypes.ts)) ensure uniqueness across multiple Redux instances on the same page. This prevents action type collisions if you load Redux from different bundles or if third-party libraries also use Redux internally.

### How does ActionTypes.REPLACE differ from manually re-creating the store?

`store.replaceReducer()` preserves the existing state tree and subscription listeners, whereas creating a new store (`createStore(newReducer)`) destroys both. `ActionTypes.REPLACE` enables hot module replacement by allowing the new reducer to initialize only its new slices while keeping existing state intact.

### Where are these action types defined in the Redux source code?

They are defined in [`src/utils/actionTypes.ts`](https://github.com/reduxjs/redux/blob/main/src/utils/actionTypes.ts) as properties of the `ActionTypes` object. The `INIT` and `REPLACE` strings are consumed in [`src/createStore.ts`](https://github.com/reduxjs/redux/blob/main/src/createStore.ts) during store initialization and reducer replacement, and in [`src/combineReducers.ts`](https://github.com/reduxjs/redux/blob/main/src/combineReducers.ts) for state shape validation and warning suppression.