Reputation: 79
I am trying to pass data from a local db.js file using redux in ReactJS. I feel like I am very close, but there is something that I am missing. I am currently getting the following error when I npm start:
TypeError: Cannot read property 'map' of undefined
This error occurred during the build time and cannot be dismissed. This error occurred during the build time and cannot be dismissed. I am at a complete lose. I have been working at this for 2 days and can not seem to figure out what it is that I am doing wrong. I did get the data to represent before I brought redux in. So I know that I have made the fetch request work on the local file. Once I brought in redux everything stopped working. If anyone could please help me it would be VERY appreciated. If there is any clarification on things, please, let me know.
I will be placing a snippet of db.json as it is to large to place the entire file. It is in
src/data/db.json
{
"hits": [
{
"_index": "issflightplan",
"_type": "issflightplan",
"_key": "IDP-ISSFLIGHTPLAN-0000000000000447",
"_version": 1,
"_score": null,
"ContentType": {
"__deferred": {
"uri": "https://bi.sp.iss.nasa.gov/Sites/FP/_api/Web/Lists(guid'a9421c5b-186a-4b14-b7b2-4b88ee8fab95')/Items(252)/ContentType"
}
I then have a page component in
src/researchPage/researchPage.js
import React, { Component } from "react";
// import ReactDOM from "react-dom";
import './reasearchPage.style.scss'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
// import { Card, Feed } from 'semantic-ui-react'
import { fetchDataSuccess } from "../../Redux/actions/researchActions";
class ResearchPage extends Component {
componentDidMount() {
this.props.fetchDataSuccess();
}
render() {
const hits = this.props.data.map(dataSet => (
<div key={dataSet.id} className="query-div">
<h3>{dataSet._index}</h3>
<p>{dataSet.ContentTypeId}</p>
</div>
))
return (
<div>
<h1>Record MetaData</h1>
{hits}
</div>
);
}
}
const mapStateToProps = state => ({
data: state.data.hits
})
export default connect(mapStateToProps, {fetchData})(ResearchPage);
I then set up Redux. I will place all of these files consecutively, below:
src/Redux/actions/dataActions.js
import data from '../../data/db.json'
export const FETCH_DATA_BEGIN = "FETCH_DATA_BEGIN";
export const FETCH_DATA_SUCCESS = "FETCH_DATA_SUCCESS";
export const FETCH_DATA_FAILURE = "FETCH_DATA_FAILURE";
export const fetchDataBegin = () => ({
type: FETCH_DATA_BEGIN
});
export const fetchDataFailure = error => ({
type: FETCH_DATA_FAILURE,
payload: { error }
});
export const fetchDataSuccess = async dispatch => {
dispatch({ type: FETCH_DATA_SUCCESS, payload: data });
};
src/Redux/reducers/data/dataReducer
import {
FETCH_DATA_BEGIN,
FETCH_DATA_SUCCESS,
FETCH_DATA_FAILURE
} from "../../actions/dataAction";
const initialState = {
data: [],
pending: false,
error: null
};
export default function dataReducer(state = initialState, action) {
switch (action.type) {
case FETCH_DATA_BEGIN:
// Mark the state as "loading" so we can show a spinner or something
// Also, reset any errors. We're starting fresh.
return {
...state,
pending: true
};
case FETCH_DATA_SUCCESS:
// All done: set loading "false".
// Also, replace the items with the ones from the server
console.log(action.payload);
return {
...state,
pending: false,
data: action.payload
};
case FETCH_DATA_FAILURE:
// The request failed. It's done. So set loading to "false".
// Save the error, so we can display it somewhere.
// Since it failed, we don't have items to display anymore, so set `items` empty.
//
// This is all up to you and your app though:
// maybe you want to keep the items around!
// Do whatever seems right for your use case.
return {
...state,
pending: false,
error: action.error,
data: []
};
default:
// ALWAYS have a default case in a reducer
return state;
}
}
src/Redux/rootReducer
import { combineReducers } from 'redux';
import { persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import dataReducer from "./reducers/data/dataReducer";
const persistConfig = {
key: 'root',
storage,
whitelist: ['cart']
};
const rootReducer = combineReducers({
data: dataReducer,
});
export default persistReducer(persistConfig, rootReducer);
src/Redux/store
import { createStore, applyMiddleware } from 'redux';
import { persistStore } from 'redux-persist';
import thunk from 'redux-thunk'
import rootReducer from './root-reducer';
export const store = createStore(rootReducer, applyMiddleware(thunk));
export const persistor = persistStore(store);
export { store, persistor };
src/App.js
import React, {Component} from 'react';
import {BrowserRouter, Route, Switch} from 'react-router-dom';
import { PersistGate } from 'redux-persist/integration/react'
import{ Provider } from 'react-redux';
import { store, persistor } from './Redux/store'
import './App.css';
import Navbar from "./components/menu/navbar";
import Home from './pages/home/home'
import Explore from './pages/explore/explore'
import search from './pages/search/search'
import researchPage from "./pages/researchPage/reasearchPage";
import Query from './pages/query/query'
import Visualize from "./pages/visualize/visualize";
import Analyze from "./pages/analyze/analyze";
import Configure from "./pages/configure/configure";
class App extends Component{
render() {
return(
<Provider store={ store }>
<PersistGate loading={null} persistor={persistor}>
<BrowserRouter>
<div>
<Navbar/>
<Switch>
<Route path="/" component={Home} exact/>
<Route path="/explore" component={Explore} exact/>
<Route path="/search" component={search} exact/>
<Route path="/query" component={Query} exact/>
<Route path="/visualize" component={Visualize} exact/>
<Route path="/analyze" component={Analyze} exact/>
<Route path="/configure" component={Configure} exact/>
<Route path="/research" component={researchPage} exact/>
</Switch>
</div>
</BrowserRouter>
</PersistGate>
</Provider>
)
}
}
export default App;
New Error:
TypeError: Cannot read property 'map' of undefined
ResearchPage.render
C:/Users/dgponder/codeRepository/insight-react/insight-react-ui/src/pages/researchPage/reasearchPage.js:15
12 | }
13 |
14 | render() {
> 15 | const hits = this.props.data.map(dataSet => (
| ^ 16 | <div key={dataSet.id} className="query-div">
17 | <h3>{dataSet._index}</h3>
18 | <p>{dataSet.ContentTypeId}</p>
View compiled
▼ 19 stack frames were expanded.
finishClassComponent
C:/Users/dgponder/codeRepository/insight-react/insight-react-ui/node_modules/react-dom/cjs/react-dom.development.js:17485
updateClassComponent
C:/Users/dgponder/codeRepository/insight-react/insight-react-ui/node_modules/react-dom/cjs/react-dom.development.js:17435
beginWork
C:/Users/dgponder/codeRepository/insight-react/insight-react-ui/node_modules/react-dom/cjs/react-dom.development.js:19073
HTMLUnknownElement.callCallback
C:/Users/dgponder/codeRepository/insight-react/insight-react-ui/node_modules/react-dom/cjs/react-dom.development.js:3945
invokeGuardedCallbackDev
C:/Users/dgponder/codeRepository/insight-react/insight-react-ui/node_modules/react-dom/cjs/react-dom.development.js:3994
invokeGuardedCallback
C:/Users/dgponder/codeRepository/insight-react/insight-react-ui/node_modules/react-dom/cjs/react-dom.development.js:4056
beginWork$1
C:/Users/dgponder/codeRepository/insight-react/insight-react-ui/node_modules/react-dom/cjs/react-dom.development.js:23964
performUnitOfWork
C:/Users/dgponder/codeRepository/insight-react/insight-react-ui/node_modules/react-dom/cjs/react-dom.development.js:22776
workLoopSync
C:/Users/dgponder/codeRepository/insight-react/insight-react-ui/node_modules/react-dom/cjs/react-dom.development.js:22707
renderRootSync
C:/Users/dgponder/codeRepository/insight-react/insight-react-ui/node_modules/react-dom/cjs/react-dom.development.js:22670
performSyncWorkOnRoot
C:/Users/dgponder/codeRepository/insight-react/insight-react-ui/node_modules/react-dom/cjs/react-dom.development.js:22293
(anonymous function)
C:/Users/dgponder/codeRepository/insight-react/insight-react-ui/node_modules/react-dom/cjs/react-dom.development.js:11327
unstable_runWithPriority
C:/Users/dgponder/codeRepository/insight-react/insight-react-ui/node_modules/scheduler/cjs/scheduler.development.js:646
runWithPriority$1
C:/Users/dgponder/codeRepository/insight-react/insight-react-ui/node_modules/react-dom/cjs/react-dom.development.js:11276
flushSyncCallbackQueueImpl
C:/Users/dgponder/codeRepository/insight-react/insight-react-ui/node_modules/react-dom/cjs/react-dom.development.js:11322
flushSyncCallbackQueue
C:/Users/dgponder/codeRepository/insight-react/insight-react-ui/node_modules/react-dom/cjs/react-dom.development.js:11309
discreteUpdates$1
C:/Users/dgponder/codeRepository/insight-react/insight-react-ui/node_modules/react-dom/cjs/react-dom.development.js:22420
discreteUpdates
C:/Users/dgponder/codeRepository/insight-react/insight-react-ui/node_modules/react-dom/cjs/react-dom.development.js:3756
dispatchDiscreteEvent
C:/Users/dgponder/codeRepository/insight-react/insight-react-ui/node_modules/react-dom/cjs/react-dom.development.js:5889
▲ 19 stack frames were expanded.
This screen is visible only in development. It will not appear if the app crashes in production.
Open your browser’s developer console to further inspect this error. Click the 'X' or hit ESC to dismiss this message.
Upvotes: 1
Views: 603
Reputation: 451
Try to add PersistGate
inside of your Provider
component like in the example below.
import { PersistGate } from 'redux-persist/integration/react'
import { store, persistor } from './Redux/store'
const App = () => {
return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<RootComponent />
</PersistGate>
</Provider>
);
};
Upvotes: 1
Reputation: 451
I found your issue. In src/Redux/store
you are using export default { store, persistor }
.
Then in the src/App.js
you are probably importing it as variable store
.
But since you didn't export store from
src/Redux/store`, instead of passing this to the provider:
<Provider store={ store }>
you are actually passing an object that contains store and persistor, like this:
<Provider store={ {store, persistor} }>
So you can fix this this way:
// src/Redux/store
export { store, persistor }; // notice I removed the word `default`
// src/App.js
import { store } from './Redux/store';
and then you can use:
<Provider store={ store }>
Upvotes: 1
Reputation: 451
In your src/researchPage/researchPage.js
you have this line
export default connect(mapStateToProps, {fetchData})(ResearchPage);
You are passing fetchData
as the second parameter to the connect, but fetchData
is not defined in this file or imported from another.
Because of this connect is broken, and neither fetchData
or data
are accessible in the component.
Upvotes: 1