ExpressJS / ReactJS постоянная проблема деструктуризации - PullRequest
0 голосов
/ 24 сентября 2018

Я использую ReactJS, ExpressJS, NodeJS, PostgreSQL, с Redux

Я пытаюсь извлечь одну строку таблицы SQL из моего бэкэнда с помощью вызова axios.Вызов возвращает запрошенные данные в объекте, вложенном в массив [{..}].Проблема возникает, когда я пытаюсь деструктурировать данные или получить к ним доступ через скобочную запись.

Если я использую эту нотацию this.props.returnedData[0] для доступа к единственному объекту в возвращаемом массиве, я получаю сообщения об ошибках, что ReturnData [0] не существует или не определено.

сохранить вНе говоря уже о том, что на самом деле он возвращал данные в массиве через console.log.

Я полагаю, это связано с тем, что componentDidMount возвращает данные после того, как React уже попытался визуализировать returnData [0].

Итак, вопросы.Есть ли способ деструктурировать или получить доступ к этим данным любым другим способом?Есть ли «лучший» способ (относительно синхронизации) для получения данных, чем при использовании componentDidMount?

Ответы [ 2 ]

0 голосов
/ 25 сентября 2018

Извините за длинное объяснение, но оно показывает все шаги ...

Давайте рассмотрим этот пример: пользователь переходит к Dashboard представлению ...

клиенту/src/containers/dashboard.js (этот контейнер HOC в основном просто передает действия и состояние Redux компоненту DashboardPanels.)

import React from 'react';
import { connect } from 'react-redux';
import { getDashboardData } from '../actions/dashboardActions';
import DashboardPanels from '../components/dashboard/DashboardPanels';

export default connect(state => ({ dashboardData: state.dashboard.data }), { getDashboardData })(props => <DashboardPanels {...props} />)

client / src / components /dashboard / DashboardPanels (компонент DashboardPanels монтируется, а затем выполняет переданное действие Redux getDashboardData() в своем методе жизненного цикла componentDidMount - ВНИМАНИЕ: если данные еще не заполнены, он показывает счетчик!)

import React, { Component } from 'react';
import { Row } from 'antd';

import PageContainer from '../app/panels/pageContainer';
import MessagesPanel from './messagesPanel';
import PlansPanel from './plansPanel';
import PromotionalsPanel from './promotionalsPanel';
import Spinner from '../app/loaders/Spinner';
import SubcribersPanel from './subscribersPanel';
import TemplatesPanel from './templatesPanel';
import TransactionsPanel from './transactionsPanel';

export default class Dashboard extends Component {     
    componentDidMount = () => this.props.getDashboardData();

    render = () => (
        !this.props.dashboardData
            ? <Spinner />
            : <PageContainer>
                <Row style={{ marginTop: 30 }}>
                    <SubcribersPanel {...this.props.dashboardData} />
                    <PlansPanel {...this.props.dashboardData} />
                    <PromotionalsPanel {...this.props.dashboardData} />
                    <TransactionsPanel {...this.props.dashboardData} />
                    <MessagesPanel {...this.props.dashboardData} />
                    <TemplatesPanel {...this.props.dashboardData} />
                </Row>
              </PageContainer>
    )
}

client / src / actions / dashboardActions.js (это делает запрос AJAX серверу API express)

import { app } from './axiosConfig';
import * as types from './types';

const getDashboardData = () => dispatch => (
    app.get(`dashboard`)
    .then(({data}) => dispatch({ type: types.SET_DASHBOARD_DATA, payload: data }))
    .catch(err => dispatch({ type: types.SERVER_ERROR, payload: err }))
)

export {
  getDashboardData
}

маршруты / dashboard.js (запрос AJAX внешнего интерфейса обращается к маршруту панели инструментов сервера API express - проходит проверку подлинности, затем отправляется на контроллер getAll)

    const { getAll } = require('../controllers/dashboard);
    const { requireRelogin, requireAuth } = require('../services/strategies');

    app.get('/api/dashboard', requireAuth, getAll);
}

controllers / dashboard.js (контроллер getAll получает запрос, запрашивает базу данных PostgresSQLnd возвращает JSON или то, что вы называете вложенным объектом в массиве [{...}].Обратите внимание, что я использую res.send() с оператором ...spread!)

const { db, query: { getAllDashboardDetails }} = require('../database);
const { beginofMonth, endofMonth, parseStringToNum, sendError } = require('../shared/helpers');

        // GETS ALL DASHBOARD DATA
    exports.getAll = async (req, res, done) => {
            const beginMonth = beginofMonth();
            const endMonth = endofMonth();

            try {
                const dashboard = await db.many(getAllDashboardDetails, [req.session.id, beginMonth, endMonth])

                return res.status(201).send(...dashboard);
            } catch (err) { return sendError(err, res, done); }
        }

панель управления JSON имеет такую ​​же структуру на серверной части:

dashboard [{
    subscribers: '146',
    inactivesubscribers: '12',
    plans: '12',
    popularplans: [ [Object], [Object], [Object], [Object], [Object], [Object] ],
    promotionals: '12',
    popularpromotionals: [ [Object], [Object], [Object], [Object], [Object], [Object] ],
    credits: '5',
    creditstotal: '149.95',
    dues: '5',
    duestotal: '149.95',
    charges: '7',
    chargestotal: '209.93',
    refunds: '7',
    refundstotal: '209.93',
    messages: '5',
    activetemplates: '4',
    inactivetemplates: '4' 
}]

client / src / redurs / index.js (однако, поскольку мы использовали res.send() с оператором ...spread, теперь он становится простым объектом к моменту сохранения в state Redux через dashboardReducer)

import { routerReducer as routing } from 'react-router-redux';
import { combineReducers } from 'redux';
import * as types from '../actions/types';

const dashboardReducer = (state = {}, { payload, type }) => {
    switch (type) {
        case types.SET_DASHBOARD_DATA:
            return {
                ...state,
                data: payload
            };
        default: return state;
    }
}

export default = combineReducers({
    dashboard: dashboardReducer,
    routing
});

Состояние dashboard в Redux теперь структурировано так:

dashboard: {
    data: {
       subscribers: '146',
       inactivesubscribers: '12',
       plans: '12',
       popularplans: [ [Object], [Object], [Object], [Object], [Object], [Object] ],
       promotionals: '12',
       popularpromotionals: [ [Object], [Object], [Object], [Object], [Object], [Object] ],
       credits: '5',
       creditstotal: '149.95',
       dues: '5',
       duestotal: '149.95',
       charges: '7',
       chargestotal: '209.93',
       refunds: '7',
       refundstotal: '209.93',
       messages: '5',
       activetemplates: '4',
       inactivetemplates: '4'
    } 
 }

Поскольку DashboardPanels подключен к Redux через компонент HOC, мы можемтеперь доступ к Redux state.dashboard.data через this.props.dashboardData.

И результат:

enter image description here

0 голосов
/ 24 сентября 2018

Если я правильно понимаю проблему, вы пытаетесь получить доступ к индексу массива, который не существует, потому что ваши данные еще не поступили.Одним из способов решения этой проблемы может быть быстрая проверка, имеет ли массив индекс до доступа к нему.Примерно так:

const data = this.props.returnedData.length > 0 ? this.props.returnedData[0]: {}

А затем вы будете использовать новую переменную «data», например, в методе рендеринга или аналогичном.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...