繁体   English   中英

在 REACTJS 中使用 Redux 传递数据

[英]Pass Data Using Redux in REACTJS

我正在尝试使用 ReactJS 中的 redux 从本地 db.js 文件传递数据。 我觉得我很接近,但我缺少一些东西。 当我启动 npm 时,我目前收到以下错误:

TypeError:无法读取未定义的属性“地图”

此错误发生在构建期间,无法消除。 此错误发生在构建期间,无法消除。 我完全输了。 我已经为此工作了 2 天,似乎无法弄清楚我做错了什么。 在我把 redux 带进来之前,我确实得到了要表示的数据。所以我知道我已经在本地文件上进行了获取请求。 一旦我带来了 redux,一切都停止了工作。 如果有人可以请帮助我,将不胜感激。 如果对事情有任何澄清,请告诉我。

我将放置一个 db.json 的片段,因为它对于放置整个文件来说太大了。 它在

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"
                }

然后我有一个页面组件

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);

然后我设置了 Redux。 我将在下面连续放置所有这些文件:

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.

在你的src/researchPage/researchPage.js你有这一行

export default connect(mapStateToProps, {fetchData})(ResearchPage);

您将fetchData作为第二个参数传递给连接,但fetchData未在此文件中定义或从另一个文件中导入。

由于这个连接被破坏,组件中既不能访问fetchData也不能访问data

我发现了你的问题。 src/Redux/store中,您使用的是export default { store, persistor }

然后在src/App.js中,您可能会将其作为变量store导入。 但是由于您没有store from因此没有将其传递给提供者:

 <Provider store={ store }>

您实际上正在传递一个包含存储和持久性的 object,如下所示:

 <Provider store={ {store, persistor} }>

所以你可以这样解决这个问题:

// src/Redux/store
export { store, persistor }; // notice I removed the word `default`

// src/App.js
import { store } from './Redux/store';

然后你可以使用:

 <Provider store={ store }>

尝试在Provider组件中添加PersistGate ,如下例所示。

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>
  );
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM