Leon Gaban
Leon Gaban

Reputation: 39018

Parameter 'initialState' cannot be referenced in its initializer

In my ReactJS / Typescript app, I'm getting the following error in my store.ts:

Parameter 'initialState' cannot be referenced in its initializer.

interface IinitialState {
  fiatPrices: [];
  wallets: [];
  defaultCurrency: string;
}

const initialState = {
  fiatPrices: [],
  wallets: [],
  defaultCurrency: ''
}

...

export function initializeStore (initialState:IinitialState = initialState) {
  return createStore(
    reducer,
    initialState,
    composeWithDevTools(applyMiddleware(thunkMiddleware))
  )
}

Anyone else run into this issue? Currently having to rely on // @ts-ignore


Entire store.ts file:

import { createStore, applyMiddleware } from 'redux'
import { composeWithDevTools } from 'redux-devtools-extension'
import thunkMiddleware from 'redux-thunk'

interface IinitialState {
  fiatPrices: [];
  wallets: [];
  defaultCurrency: string;
}

const initialState = {
  fiatPrices: [],
  wallets: [],
  defaultCurrency: ''
}

export const actionTypes = {
  GET_PRICES: 'GET_PRICES'
}

// REDUCERS
export const reducer = (state = initialState, action: any) => {
  switch (action.type) {
    case actionTypes.GET_PRICES:
      return state
    default:
      return state
  }
}

// MOCK API
export async function getProgress(dispatch: any) {
  try {
    const priceList = await fetchPrices();
    return dispatch({ type: actionTypes.GET_PRICES, payload: priceList })
  }
  catch (err) {
    console.log('Error', err);
  }
}

// Wait 1 sec before resolving promise
function fetchPrices() {
  return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({ progress: 100 });
      }, 1000);
  });
}

// ACTIONS
export const addLoader = () => (dispatch: any) => {
  getProgress(dispatch);
}

// @ts-ignore
export function initializeStore (initialState:IinitialState = initialState) {
  return createStore(
    reducer,
    initialState,
    composeWithDevTools(applyMiddleware(thunkMiddleware))
  )
}

withReduxStore lib file

import React from 'react'
import { initializeStore, IinitialState } from '../store'

const isServer = typeof window === 'undefined'
const __NEXT_REDUX_STORE__ = '__NEXT_REDUX_STORE__'

function getOrCreateStore (initialState: IinitialState) {
  // Always make a new store if server, otherwise state is shared between requests
  if (isServer) {
    return initializeStore(initialState)
  }

  // Create store if unavailable on the client and set it on the window object
  // Waiting for (@ts-ignore-file) https://github.com/Microsoft/TypeScript/issues/19573 to be implemented
  // @ts-ignore
  if (!window[__NEXT_REDUX_STORE__]) {
    // @ts-ignore
    window[__NEXT_REDUX_STORE__] = initializeStore(initialState)
  }
  // @ts-ignore
  return window[__NEXT_REDUX_STORE__]
}

// @ts-ignore
export default App => {
  return class AppWithRedux extends React.Component {
    // @ts-ignore
    static async getInitialProps (appContext) {
      // Get or Create the store with `undefined` as initialState
      // This allows you to set a custom default initialState
      const reduxStore = getOrCreateStore()

      // Provide the store to getInitialProps of pages
      appContext.ctx.reduxStore = reduxStore

      let appProps = {}
      if (typeof App.getInitialProps === 'function') {
        appProps = await App.getInitialProps(appContext)
      }

      return {
        ...appProps,
        initialReduxState: reduxStore.getState()
      }
    }

    // @ts-ignore
    constructor (props) {
      super(props)
      this.reduxStore = getOrCreateStore(props.initialReduxState)
    }

    render () {
      return <App {...this.props} reduxStore={this.reduxStore} />
    }
  }
}

Upvotes: 1

Views: 754

Answers (1)

Estus Flask
Estus Flask

Reputation: 222513

function initializeStore (initialState:IinitialState = initialState) { ... }

is not valid by any means, not just in TypeScript. It's incorrect to suppress the error with @ts-ignore.

initialState parameter shadows the variable of the same name from enclosing scope, so default parameter value refers the parameter itself. This will result in discarding default parameter value with ES5 target and in an error with ES6 target.

The parameter and default value should have different names:

function initializeStore (initialState:IinitialState = defaultInitialState) { ... }

Notice that the use of defaultInitialState isn't needed in a reducer, due to how initial state works. Initial state from createStore takes precedence if combineReducers is not in use.

Upvotes: 1

Related Questions