@ak_wi

Как преобразовать функцию в класс React?

Есть функция getResourcesAction:
import isEmpty from 'lodash/isEmpty';

export const LOAD_RESOURCES = 'Resources/LOAD_RESOURCES';

export const getResourcesAction = () => async (dispatch, getState) => {
  const { resources } = getState();
  if (isEmpty(resources)) {
    const res = await fetch('/api/resources/all', { credentials: 'include' });
    const data = await res.json();
    dispatch({
      type: LOAD_RESOURCES,
      payload: {
        resources: data,
      },
    });
  }
};

const initialState = {};

export default function resourcesState(state = initialState, action) {
  switch (action.type) {
    case LOAD_RESOURCES:
      return action.payload.resources;
    default:
      return state;
  }
}


Как преобразовать ее в класс, чтобы добавить state с параметром загрузки, который потом можно было бы получать в других частях приложения?
import React, { Component } from 'react';
import { Redirect, Route, Switch, withRouter } from 'react-router-dom';

import Header from 'components/Header';
import Sidebar from 'components/Sidebar';
import Footer from 'components/Footer';
import Scrollbar from 'react-scrollbars-custom';

import { style } from 'variables';

import routes from 'routes';
import { connect } from 'react-redux';
import { getResourcesAction } from 'modules/Resources';
import isEmpty from 'lodash/isEmpty';
import { getProfileAction } from 'modules/Profile';
import { defaultNotification } from 'modules/Notifications';
import Notifications from 'react-notification-system-redux';
import { getProgressAction } from 'modules/Progress';
import PropTypes from 'prop-types';
import { getTeamsAction } from 'modules/Teams';

class App extends Component {
  scrollRef = React.createRef();
  static propTypes = {
    resources: PropTypes.object,
    notifications: PropTypes.array,
    getResourcesAction: PropTypes.func,
    getProgressAction: PropTypes.func,
    getProfileAction: PropTypes.func,
    defaultNotification: PropTypes.func,
  };
  componentDidMount() {
    if (isEmpty(this.props.resources)) {
      this.props.getResourcesAction();
      this.props.getProgressAction();
      this.props.getProfileAction();
      this.props.getTeamsAction();
    }
  }

  componentDidUpdate(e) {
    if (e.history.action === 'PUSH') {
      document.documentElement.scrollTop = 0;
      document.scrollingElement.scrollTop = 0;
      this.scrollRef.current.scrollToTop();
    }
    if (
      this.props.location.pathname.includes('/code-task') &&
      document.body.className.indexOf('sidebar-mini') === -1
    ) {
      document.body.classList.toggle('sidebar-mini');
    }
    if (
      window.innerWidth < 993 &&
      e.history.location.pathname !== e.location.pathname &&
      document.documentElement.className.indexOf('nav-open') !== -1
    ) {
      document.documentElement.classList.toggle('nav-open');
    }
  }

  render() {
    if (isEmpty(this.props.resources)) {
      return null;
    }
    return (
      <div className="main-wrapper">
        <Notifications notifications={this.props.notifications} style={style} />
        <Sidebar {...this.props} />
        <div id="main-panel" className="main-panel">
          <Scrollbar ref={this.scrollRef} noScrollX style={{ height: '100%' }}>
            <Header {...this.props} />
            <Switch>
              {routes().map(prop => {
                // Не создаем роут для splitter
                if (prop.splitter) {
                  return null;
                }
                if (prop.redirect) {
                  return (
                    <Redirect
                      from={prop.path}
                      to={prop.to}
                      key={prop.path + prop.to}
                    />
                  );
                }
                return (
                  <Route
                    path={prop.path}
                    render={prop.render}
                    component={prop.component}
                    key={prop.path}
                  />
                );
              })}
            </Switch>
            <Footer />
          </Scrollbar>
        </div>
      </div>
    );
  }
}

const mapStateToProps = state => ({
  resources: state.resources,
  vector: state.vector,
  profile: state.profile,
  notifications: state.notifications,
  progress: state.progress,
  teams: state.teams,
});

const mapDispatchToProps = {
  getResourcesAction,
  getProfileAction,
  defaultNotification,
  getProgressAction,
  getTeamsAction,
};

export default withRouter(
  connect(
    mapStateToProps,
    mapDispatchToProps,
  )(App),
);
  • Вопрос задан
  • 177 просмотров
Решения вопроса 1
rockon404
@rockon404 Куратор тега React
Frontend Developer
Как преобразовать ее в класс, чтобы добавить state с параметром загрузки, который потом можно было бы получать в других частях приложения?

Срочно изучайте теорию.

Пример решения:
export const getResourcesAction = () => async (dispatch, getState) => {
  const { resources } = getState();
  if (isEmpty(resources)) {
    try {
      dispatch({ type: LOAD_RESOURCES_REQUEST });

      const res = await fetch('/api/resources/all', { credentials: 'include' });
      const data = await res.json();
      dispatch({
        type: LOAD_RESOURCES_SUCCEEDED,
        payload: {
          resources: data,
        },
      });
    } catch (error) {
      dispatch({
        type: LOAD_RESOURCES_FAILED,
        payload: {
          error,
        },
      });
    }
  }
};

const initialState = {
  isFetching: false,
  data: [],
  error: null,
};

export default function resourcesState(state = initialState, action) {
  switch (action.type) {
    case LOAD_RESOURCES_REQUEST:
      return {
        ...state,
        isFetching: true,
        error: null,
      };
    case LOAD_RESOURCES_SUCCEEDED:
      return {
       data: action.payload.resources,
        isFetching: false,
      };
   case LOAD_RESOURCES_FAILED:
      return {
        ...state,
        isFetching: false,
        error: action.payload.error,
      };
    default:
      return state;
  }
}
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы