Redux connect方法失效,无法从store获取数据求助
Hey there! Let's figure out why you're hitting that "contactsList is undefined" error when trying to map over your contacts. I've spotted a few key issues in your code that are causing this problem—let's break them down and fix them step by step:
1. Wrong state path in mapStateToProps
You used combineReducers({ dataReducer }) to combine your reducers, which means your Redux store's state structure looks like this:
{ dataReducer: { contactsList: [...] // Your actual contacts live here } }
But in your ContactCards.js, you're trying to access state.contactsList directly—this property doesn't exist! You need to traverse through the dataReducer key first.
Fixed mapStateToProps in ContactCards.js:
const mapStateToProps = state => { return { contactsList: state.dataReducer.contactsList }; };
2. Broken state structure in the updateContacts reducer case
In your dataReducer, when handling the updateContacts action, you're returning updatedItems directly. This replaces the entire state object with just the contacts array—after this action runs, the state won't have a contactsList property anymore, which will trigger the same undefined error.
You need to preserve the original state shape by returning a new object with the updated contactsList:
Fixed updateContacts case in dataReducer.js:
case UPDATE_CONTACTS: // We'll fix the action type next! const updatedItems = state.contactsList.map(item => { if(item.id === action.id){ return { ...item, ...action.payload } } return item }) return { ...state, contactsList: updatedItems }; // Keep the state structure intact
3. Action type mismatch (using creators instead of string constants)
Right now, you're using loadContacts and updateContacts (which are action creator functions) directly in your reducer's switch cases. Redux matches action types as strings, so these cases will never catch any dispatched actions.
First, update your CardActions.js to define string constants for action types:
// Define action type constants export const LOAD_CONTACTS = 'LOAD_CONTACTS'; export const UPDATE_CONTACTS = 'UPDATE_CONTACTS'; // Action creators using the constants export const loadContacts = () => ({ type: LOAD_CONTACTS }); export const updateContacts = (id, payload) => ({ type: UPDATE_CONTACTS, id, payload });
Then update your reducer to use these constants:
import ContactsList from '../components/MockContactsList'; // Import the string constants instead of just the creators import { LOAD_CONTACTS, UPDATE_CONTACTS } from '../Actions/CardActions'; const INITIAL_STATE = { contactsList: ContactsList }; const dataReducer = (state = INITIAL_STATE, action) => { switch(action.type) { case LOAD_CONTACTS: // Use the constant here return state; case UPDATE_CONTACTS: // And here const updatedItems = state.contactsList.map(item => { if(item.id === action.id){ return { ...item, ...action.payload } } return item }) return { ...state, contactsList: updatedItems }; default: return state; } }; export default dataReducer;
4. Initial state override (minor but important)
In your index.js and App.js, you're passing an empty object {} as the second argument to createStore. This overrides the initial state you defined in your reducer. Remove that argument to let the reducer use its INITIAL_STATE:
const store = createStore(reducers); // No empty object here
Once you apply all these fixes, your contactsList should be properly pulled from the Redux store, and you won't get the undefined error anymore.
内容的提问来源于stack exchange,提问作者user2156888

