Действие не запускается в React / Redux - PullRequest
0 голосов
/ 18 апреля 2020

Я новичок в редуксе и пытаюсь получить контент из моего BackEnd API. По какой-то причине вызываемое мной действие не достигает редуктора (оно даже не выполняется). Сначала я подумал, что это потому, что он не может получить доступ к хранилищу, поскольку у него есть родительский компонент, но мой провайдер хорошо настроен, и на том же уровне есть другой компонент, и сразу после того, как я начал думать, что это была проблема с моей отправкой, но честно говоря, я не знаю. Я приложил код, который, по моему мнению, является уместным, и любой вклад будет высоко оценен.

действий / зрителей. js

import axios from 'axios';
import { VIEWERS_LOADED, VIEWERS_ERROR } from './types';

export const loadData = async (body, http) => {
  const config = {
    headers: {
      'Content-Type': 'application/json',
    },
  };
  try {
    const res = await axios.post(
      http,
      body,
      config
    );
    return res.data;
  } catch (error) {
    console.log(error);
  }
};

export const extractConcurrentViewers = (from, to, aggregate) => async dispatch => {
  console.log("CONCURRENT VIEWERS");
  const body = {
    session_token: localStorage.token,
    from,
    to,
  };

  try {
    let aggregateConcur = null;
    const graphConccur = await loadData(body, 'http://localhost:5000/audience');
    console.log('extractViews -> res_1', graphConccur);

    if (aggregate !== null) {
        body.aggregate = aggregate
        aggregateConcur = await loadData(body, 'http://localhost:5000/audience');
    }
    console.log('extractaggregateViewers -> res_2', aggregateConcur);

    dispatch({
      type: VIEWERS_LOADED,
      payload: {
        graphConccur,
        aggregateConcur
      },
    }); 
  } catch (error) {
    console.log(error);
    dispatch({
      type: VIEWERS_ERROR,
    });
  }
}

редукторы / зрители. js

import {
    VIEWERS_LOADED,
    VIEWERS_ERROR,
  } from '../actions/types';

  const initialState = {
    session_token: localStorage.getItem('token'),
    concurrence: null,
    aggConcurrence: null,
  };

  export default function (state = initialState, action) {
    const { type, payload } = action;

    switch (type) {
      case VIEWERS_LOADED:
        return {
          ...state,
          ...payload,
          concurrence: payload.graphConccur.audience,
          aggConcurrence: payload.aggregateConcur.audience,
        };
      case VIEWERS_ERROR:
        return {
          ...state,
          concurrence: null,
          aggConcurrence: null,
        };
      default:
        return state;
    }
  }

редуктор / индекс. js

import {combineReducers} from 'redux';
import alert from './alert';
import auth from './auth'
import profile from './profile'
import chart from './chart'
import viewers from './viewers'


export default combineReducers({
    alert,
    auth,
    profile,
    chart,
    viewers
});

Приложение. js

import React, { useEffect } from 'react';
import Navbar from './components/layout/Navbar';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Landing from './components/layout/Landing';
import Login from './components/auth/Login';
import Register from './components/auth/Register';
import Alert from './components/layout/Alert';
import Dashboard from './components/dashboard/Dashboard';
import PrivateRoute from './components/routing/PrivateRouting';
import { Provider } from 'react-redux';
import store from './store';
import { loadUser } from './actions/auth';
import setAuthToken from './utils/setAuthToken'
import './App.css';

if (localStorage.token) {
  setAuthToken(localStorage.token);
}

const App = () => {

  useEffect(() => {
    store.dispatch(loadUser())
  }, []);

  return (
    <Provider store={store}>
      <Router>
        <Navbar />
        <Route exact path='/' component={Landing} />
        <section className='container'>
          <Alert />
          <Switch>
            <Route exact path='/login' component={Login} />
            <Route exact path='/register' component={Register} />
            <PrivateRoute exact path='/dashboard' component={Dashboard} />
          </Switch>
        </section>
      </Router>
    </Provider>
  );
};

export default App;

Именно здесь должна вызываться функция extractConcurrentViewers, а компонент, который предполагается использовать, - <Concurrent concurrence={concurrence}/>, и что действительно странно, так это то, что компонент чуть выше него реализован почти так же кстати, но работает.

import React, { useEffect, Fragment } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import Spinner from '../layout/Spinner';
import BandWidth from './BandWidth';
import Concurrent from './Concurrent';
import { extractCurrentClient } from '../../actions/profile';
import { extractchartData } from '../../actions/chart';
import { extractConcurrentViewers } from '../../actions/viewers';

const Dashboard = ({
  extractCurrentClient,
  extractchartData,
  auth: { user },
  profile: { profile, loading },
  chart: { cdn, p2p, maxSum, maxCdn },
  viewers: {concurrence}
}) => {
  useEffect(() => {
    extractCurrentClient();
    extractchartData('max', 1585834831000, 1589118031000);
    extractConcurrentViewers(1585834831000, 1589118031000);
  }, []);
  return loading && profile === null ? (
    <Spinner />
  ) : (
    <Fragment>
      <h1 className='large text-primary'>Streaming</h1>
      <p className='lead'>
        <i className='fas fa-chart-line'></i>
        Welcome {user && user.lname}
      </p>
      <BandWidth cdn={cdn} p2p={p2p} maxSum={maxSum} maxCdn={maxCdn} />
      {/* <Concurrent concurrence={concurrence}/> */}
    </Fragment>
  );
};

Dashboard.propTypes = {
  extractCurrentClient: PropTypes.func.isRequired,
  extractchartData: PropTypes.func.isRequired,
  extractConcurrentViewers: PropTypes.func.isRequired,
  auth: PropTypes.object.isRequired,
  profile: PropTypes.object.isRequired,
};

const mapStateToProps = (state) => ({
  auth: state.auth,
  profile: state.profile,
  chart: state.chart,
  viewers: state.viewers,
});

export default connect(mapStateToProps, {
  extractCurrentClient,
  extractchartData,
  extractConcurrentViewers
})(Dashboard);

магазин. js

import { createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import thunk from 'redux-thunk';
import rootReducer from './reducers';

const initialState = {};

const middleware = [thunk];

const store = createStore(
  rootReducer,
  initialState,
  composeWithDevTools(applyMiddleware(...middleware))
);

export default store;

1 Ответ

1 голос
/ 18 апреля 2020

Вы сопоставили extractConcurrentViewers с реквизитами в connect, но не добавили его в объект с деструктурированными реквизитами. Поскольку они имеют одно и то же имя, это означает, что вы называете своего создателя действия без привязки к dispatch, поэтому оно не будет доставлено вашим редукторам.

const Dashboard = ({
  extractCurrentClient,
  extractchartData,
  auth: { user },
  profile: { profile, loading },
  chart: { cdn, p2p, maxSum, maxCdn },
  viewers: {concurrence},
  extractConcurrentViewers // <-- add this
}) => {

Лично я не разрушить мою props и это одна из причин. Я предпочитаю, чтобы код был явным о том, откуда берутся значения и функции props.extractConcurrentViewers. Но это мое предпочтение.

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