Search code examples
javascriptecmascript-6reduxredux-thunk

are javascript const really constant? in redux?


I have this reducer in my store, where the initial state initialProcessingState is imported from another source file.

import {
  ACTN_IS_PROCESSING
} from '../config/action-types.js';

import { initialProcessingState } from "./redProcessing-initial.js";

export default function (state = initialProcessingState, action) {
  switch (action.type) {

    case ACTN_IS_PROCESSING:
      return {
        ...state,
        ...action.isProcessing
      }

    default:
      return state;
  }
}

here is how is defined in the source file:

export const initialProcessingState = {
  keys: [],
  mostRecentStatus: false,
  neverStale: true
}

Now my store is persisting state into localstorage with subscribe

  store.subscribe(() => {
    updateLocalStorage(store);
  })

Like this...

import { initialProcessingState } from "../reducers/redProcessing-initial.js";

var updateLocalStorage = debounce((store) => {
  const state = store.getState();
  var _state = {
    ...state,
    isProcessing: { ...initialProcessingState }
  };
  localStorage.setItem('reduxState', JSON.stringify(_state))
}, 100);

Where my intent is to overwrite isProcessing with it's initial state, defined as const above in initialProcessingState.

Unfortunately doesn't work. Because every single time updateLocalStorage is called the value of initialProcessingState is not the initial value, but the current updated state by subsequent reducer calls.

How is it possible? It's a const.

My temporary fix is involve JSON.parse(JSON.stringify(initialProcessingState)):

const _initialProcessingState = JSON.parse(JSON.stringify(initialProcessingState));

var updateLocalStorage = debounce((store) => {
  const state = store.getState();
  //this is not the best way
  console.log("updateLocalStorage", "initialProcessingState", initialProcessingState, _initialProcessingState);
  var _state = {
    ...state,
    isProcessing: { ..._initialProcessingState }
  };
  localStorage.setItem('reduxState', JSON.stringify(_state))
}, 100);

And the following was not enough to make it working:

const _initialProcessingState = initialProcessingState;

Can someone help?


Solution

  • The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned. For instance, in the case where the content is an object, this means the object's contents (e.g., its properties) can be altered.

    Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

    EDIT

    It might be important to mention Object.freeze() as @Apolo pointed out in his comment.

    Objects

    The Object.freeze() method freezes an object. A frozen object can no longer be changed; freezing an object prevents new properties from being added to it, existing properties from being removed, prevents changing the enumerability, configurability, or writability of existing properties, and prevents the values of existing properties from being changed. In addition, freezing an object also prevents its prototype from being changed.

    With Object.freeze() however it's also important to note that it's not extended to the values that the frozen object holds:

    Note that values [of Objects] that are objects can still be modified, unless they are also frozen.

    Arrays

    As an object, an array can be frozen; after doing so, its elements cannot be altered and no elements can be added to or removed from the array.

    Source in the EDIT section: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze