KFrancis
KFrancis

Reputation: 302

Failed prop type. Required prop types are undefined in my redux store

So I'm learning react and redux and I get this error in the console whenever I load my page. I'm not sure what it means since my store should be connected properly (as far as I know, but obviously it's not).

Warning: Failed prop type: The prop open is marked as required in >Navigation, but its value is undefined.

This is component (shortened to the key parts I think)

Navigation.propTypes = {
    open: PropTypes.bool.isRequired,
};

const mapStateToProps = (state: any) => ({
    open: state.open,
})

export default connect(mapStateToProps, { shiftContent })(Navigation);

My action

export const shiftContent = (open: boolean) => {
    return {
        type: ContentTypes.SHIFT_CONTENT,
        payload: open
    }
}

My Reducer:

const initialState = {
    open: false,
};

export default function(state = initialState, action: IAction) {
    switch(action.type) {
        case ContentTypes.SHIFT_CONTENT:
            console.log("shifting Open = " + action.payload);
            return {
                ...state,
                open: action.payload
            };
        default:
            return state;
    }
}

My combined reducer:

import ContentReducer from './ContentReducer';

const rootReducer = combineReducers({
    content: ContentReducer
});

And where I'm initializing my store:

import rootReducer from './Reducers';

const store = createStore(rootReducer);

I tried setting up an initial state for the store like:

const initialStore = {
   open: false
}
const store = createStore(rootReducer, initialStore);

But that gave me an error as well.

Upvotes: 0

Views: 317

Answers (2)

Nicholas Tower
Nicholas Tower

Reputation: 85191

const mapStateToProps = (state: any) => ({
    open: state.open,
})

in this function, state is the root state. Ie, the one produced by the rootReducer. This state looks like:

{
  content: {
    open: // some boolean
  }
}

So to access it, you need to do:

const mapStateToProps = (state: any) => ({
    open: state.content.open,
})

PS, since you're using typescript, you should be able to do better than any for the type. At the very least, you could do this:

// in the file with the root reducer:
const rootReducer = combineReducers({
    content: ContentReducer
});
export type RootState = ReturnType<typeof rootReducer>;

// And then use it elsewhere like:
const mapStateToProps = (state: RootState) => ({
    open: state.content.open,
})

Upvotes: 3

azundo
azundo

Reputation: 6052

mapStateToProps gets your root reducer state - so use state.content.open instead of state.open.

Upvotes: 0

Related Questions