简体   繁体   中英

React redux - object is possibly 'undefined

I'm getting a Typescript error that an object I'm using from Redux is possibly undefined, even though I don't say it's type can be undefined or set it to undefined anywhere.

/redux/globalSettings/actions.ts

import { ADD_GLOBAL_SETTINGS } from '../../config/actions';
import { AddGlobalSettingsAction } from './types';
import GlobalSettings from '../../typings/contentful/GlobalSettings';

export const addGlobalSettings = (payload: GlobalSettings): AddGlobalSettingsAction => ({
  type: ADD_GLOBAL_SETTINGS,
  payload,
});

/redux/globalSettings/reducers.ts

import { ADD_GLOBAL_SETTINGS } from '../../config/actions';
import { GlobalSettingsAction, GlobalSettingsState } from './types';

export default (
  state: GlobalSettingsState,
  action: GlobalSettingsAction,
): GlobalSettingsState  => {
  switch (action.type) {
    case ADD_GLOBAL_SETTINGS:
      return { ...action.payload };
    default:
      return state;
  }
}

/redux/globalSettings/types.ts

import { ADD_GLOBAL_SETTINGS } from '../../config/actions';
import GlobalSettings from '../../typings/contentful/GlobalSettings';

export type GlobalSettingsState = GlobalSettings;

export interface AddGlobalSettingsAction {
  payload: GlobalSettings;
  type: typeof ADD_GLOBAL_SETTINGS;
}

export type GlobalSettingsAction = AddGlobalSettingsAction;

/redux/reducer.ts

import { combineReducers } from 'redux';
import globalSettings from './globalSettings/reducers';

const rootReducer = combineReducers({
  globalSettings,
});

export type StoreState = ReturnType<typeof rootReducer>;

export default rootReducer;

/redux/index.ts

import { applyMiddleware, createStore } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension/developmentOnly';
import rootReducer, { StoreState } from './reducer';

export const initialiseStore = (
  initialState: StoreState,
) => createStore(
  rootReducer,
  initialState,
  composeWithDevTools(applyMiddleware()),
);

I use this in my NextJS project by using next-redux-wrapper NPM package (a React HOC) on the export of my _app.js page like so:

export default withRedux(initialiseStore)(Page);

I get an error in /redux/reducer.ts of: Type 'undefined' is not assignable to type 'GlobalSettings' .

If I use the globalSettings redux state on one of my pages, accessing globalSettings.fields.navigationLinks creates another Typescript error that globalSettings might be undefined.

Driving me crazy, what have I done wrong here?

The error

I get an error in /redux/reducer.ts of: Type 'undefined' is not assignable to type 'GlobalSettings'

relates to how you defined reducer

It should be

const initalState: GlobalSettingsState = {/* valid inital state */};

export default (
    state: GlobalSettingsState | undefined = initalState,
    action: GlobalSettingsAction,
): GlobalSettingsState  => {
    switch (action.type) {
        case ADD_GLOBAL_SETTINGS:
            return { ...action.payload };
        default:
            return state;
    }
}

Reducer can be called with state set to undefined (to initialize state). So state argument should has undefined as possible value.

I had an issue similar to this when I added extraReducers to a pre-existing reducers dict (using redux-toolkit ). All of my reducers previously fine had TypeScript errors around either

WritableDraft<WritableDraft<MySlice>>

and/or

Type 'undefined' is not assignable to type 'WritableDraft<MySlice>'

It turns out one of my reducers was returning undefined instead of state ( redux-toolkit uses immer so I guess it may work despite return undefined ).

Returning state fixed it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM