0

I'm kind of new to React.js & Redux, so I have encountered a problem with Reducers.

I am creating a site that have a main "Articles" page, "Question & Answers" page, I created for each one a separate Reducer that both work just fine.

The problem is in "Main Page" which contains a lot of small different pieces of information, and I don't want to create each little different piece of information its on Reducer, so I am trying to create one Reducer which will handle a lot of very small different pieces of information, and I can't make that work, inside the main "Content" object, I put 2 Key Value Pairs that each have an array, one for each different information, one is "Features" info, and one for the "Header" info.

This is the error that I'm getting:

Uncaught TypeError: Cannot read property 'headerContent' of undefined
    at push../src/reducers/ContentReducer.js.__webpack_exports__.default (ContentReducer.js:15)

I am not sure what's the problem, maybe my code is wrong or maybe my use of the spread operator, any solution?

I have added the necessary pages from my code:

ACTIONS FILE

export const addFeatureAction = (
    {
        title = 'Default feature title',
        feature = 'Default feature',
    } = {}) => ({
        type: 'ADD_FEATURE',
        features: {
            id: uuid(),
            title,
            feature
        }
})

export const addHeaderAction = (
    {
        title = 'Default header title',
        head = 'Default header',
    } = {}) => ({
        type: 'ADD_HEADER',
        header: {
            id: uuid(),
            title,
            head
        }
})

REDUCER FILE:

const defaultContentReducer = {
    content: {
        featuresContent: [],
        headerContent: [],
    }
}

export default (state = defaultContentReducer, action) => {
    switch(action.type) {
        case 'ADD_FEATURE':
            return [
                ...state.content.featuresContent,
                action.features
            ]
        case 'ADD_HEADER':
            return [
                ...state.content.headerContent,
                action.header
            ]
        default:
            return state
    }
}

STORE FILE:

export default () => {
    const store = createStore(
        combineReducers({
            articles: ArticleReducer,
            qnaList: QnaReducer,
            content: ContentReducer
        })
    );
    return store;
}
Jason Aller
  • 3,541
  • 28
  • 38
  • 38

1 Answers1

1

The reducer function is supposed to return the next state of your application, but you are doing a few things wrong here, you are returning an array, a piece of the state and not the state object, I would suggest you look into immer to prevent this sort of errors.

Simple fix:

export default (state = defaultContentReducer, action) => {
    switch(action.type) {
        case 'ADD_FEATURE':
            return {...state, content: {...state.content. featuresContent: [...action.features, ...state.content.featuresContent]}}
        // More actions are handled here
        default:
            return state
    }
}

If you use immer, you should have something like this

export default (state = defaultContentReducer, action) => {
  const nextState = produce(state, draftState => {
     switch(action.type) {
        case 'ADD_FEATURE':
            draftState.content.featuresContent = [...draftState.content.featuresContent, ...action.features]
  });
            break;
        default:
            break;

  return nextState
}
Oscar Franco
  • 5,691
  • 5
  • 34
  • 56