Reputation: 919
I am trying to use propTypes to help typeCheck/validate data in my app. The data comes through fine but I get a warning; Warning: Failed prop type: The prop
allSubjectSubcategoriesis marked as required in
OddMainPage, but its value is
undefined`.
I've read through some of the other responses but I haven't yet fpound a solution to fix my issues.
COMPONENT
class OddMainPage extends React.Component {
constructor(props) {
super(props);
this.state = {
categoryTables: [],
tableColumns: [],
gettingColumns: false,
selectedCategory: "",
selectedTable: ""
}
}
componentDidMount() {
this.props.dispatch(getAllSubjectSubCategories());
}
//more code to render some data
}}
OddMainPage.propTypes = {
allSubjectSubcategories: PropTypes.array.isRequired,
subCategoryTables: PropTypes.array,
tableColumns: PropTypes.array
}
const mapStateToProps = state => ({
allSubjectSubcategories: state.allSubjectSubcategories.allSubjectSubcategories,
subCategoryTables: state.subCategoryTables.subCategoryTables,
tableColumns: state.tableColumns.tableColumns
})
export default connect(mapStateToProps)(OddMainPage);
REDUCER
const initialState = {
subCategoryTables: [],
allSubjectCategories: [],
allSubjectSubcategories: []
}
export const getAllSubjectSubcategoriesReducer = (state = initialState.allSubjectSubcategories, action) => {
switch (action.type) {
case "GET_ALL_SUBJECT_SUBCATEGORIES":
return {
...state,
allSubjectSubcategories: action.allSubCats
}
default:
return initialState.allSubjectSubcategories
}
}
I also tried setting default state to default: return state
but get the same results.
STORE
import { createStore, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import rootReducer from "../reducers";
const initialState = {};
const middleware = [thunk];
let store;
if (window.navigator.userAgent.includes("Chrome")) {
store = createStore(
rootReducer,
initialState,
compose(
applyMiddleware(...middleware),
window.__REDUX_DEVTOOLS_EXTENSION__ &&
window.__REDUX_DEVTOOLS_EXTENSION__()
)
);
} else {
store = createStore(
rootReducer,
initialState,
compose(applyMiddleware(...middleware))
);
}
export default store;
Upvotes: 0
Views: 80
Reputation: 6052
It looks like you're changing the return type of your reducer form an array to an object on the GET_ALL_SUBJECT_SUBCATEGORIES
action.
Looking at initialState
for getAllSubcategoriesReducer
, you can see the value is an array. However the return value for the GET_ALL_SUBJECT_SUBCATEGORIES
branch is an object. You'll need to standardize on one or the other.
Since the initial state of the reducer is just an empty array, the value of state.allSubjectSubcategories
in mapStateToProps
will be that empty array. So when you call allSubjectSubcategories: state.allSubjectSubcategories.allSubjectSubcategories,
you get undefined
.
If you want to keep the nested version you will need to change initialState
(and fix the default case of the reducer):
// NOTE: I've nested all of your sub-reducer keys to match your `mapStateToProps`.
const initialState = {
subCategoryTables: {
subCategoryTables: [],
},
allSubjectCategories: {
allSubjectCategories: [],
},
allSubjectSubcategories: {
allSubjectSubcategories: [],
}
}
export const getAllSubjectSubcategoriesReducer = (state = initialState.allSubjectSubcategories, action) => {
switch (action.type) {
case "GET_ALL_SUBJECT_SUBCATEGORIES":
return {
...state,
allSubjectSubcategories: action.allSubCats
}
// return `state` here or you will keep reseting your reducer state
default:
return state
}
}
If you want to keep the reducer as an array like the initial state you will need to update your reducer and your mapStateToProps
:
export const getAllSubjectSubcategoriesReducer = (state = initialState.allSubjectSubcategories, action) => {
switch (action.type) {
case "GET_ALL_SUBJECT_SUBCATEGORIES":
// assuming action.allSubCats is an array, we want to replace this entire reducer state with the new array
return action.allSubCats
// return `state` here or you will keep reseting your reducer state
default:
return state
}
}
Now that the reducer above always returns an array you can update your mapStateToProps
to remove the extra key being introduced before:
const mapStateToProps = state => ({
allSubjectSubcategories: state.allSubjectSubcategories, // note the change here
// you probably want these to be updated as well with similar changes to your other reducers
subCategoryTables: state.subCategoryTables,
tableColumns: state.tableColumns
})
Upvotes: 1