React - растет кол-во “бесполезного” кода

192
19 февраля 2018, 04:39

Есть контейнер, который подключен к Redux'у. Этот контейнер, по сути, управляет всем приложением.

Метод в моем контейнере, который возвращает модальное окно «ModalPostSelect»:

createModalPostSelect(callbackOpen, callbackClose, callbackSelectPost, callbackPostExportStart, callbackLoadCheckLoop, posts) {
  const startExport = (postId) => {
    callbackSelectPost(postId);
    callbackPostExportStart();
    callbackLoadCheckLoop();
    callbackOpen(MODAL_EXPORT_PROGRESS);
  };
  return <ModalPostSelect
    callbackClose={callbackClose} 
    callbackPostSelect={startExport}
    posts={posts}
  />;
}

Обратите внимание на то, сколько у метода параметров. Уже здесь у меня закрадываются подозрения, что что-то идет не так... Слишком уж их много. Часть метода render контейнера:

{ this.props.modals.current === MODAL_POST_SELECT && this.createModalPostSelect(
  this.props.actionModalOpen,
  this.props.actionModalClose,
  this.props.actionCommentsLoadSelectPost,
  this.props.actionCommentsLoadStart,
  this.props.actionCommentsLoadCheckLoop,
  this.props.commentsLoad.posts
) }

В чем, собственно, проблема - на сколько я понимаю, «правильно» передавать все необходимое для работы метода в качестве параметров, это облегчает тестирование, позволяет создавать чистые функции и т.д.

Но как быть, блин, с таким количеством бесполезного кода? Сначала передаем 6 параметров в метод, а потом еще и в самом методе тупо передаем данные/колбеки дальше. Бред же? Как упростить и сократить код, не растеряв при этом его качества?

Код контейнера целиком:

import React, { Component } from 'react';
import { connect } from "react-redux";
// Constants
import {
  STATUS_ERROR,
  STATUS_LOADING,
  STATUS_OK,
  MODAL_HELP,
  MODAL_ACCOUNT_SELECT,
  MODAL_POST_SELECT,
  MODAL_EXPORT_PROGRESS,
} from '../reducers/constants';
// Reducers
import {
  dialogsLoad,
  dialogSelect,  
  dialogMarkAsRead,
  commentSelect,
  commentAnswerEdit,
  commentAnswerSend,
  commentDelete
} from '../reducers/Dialogs';
import {
  accountsLoad
} from '../reducers/Accounts';
import Dialogs from '../components/Dialogs/Dialogs';
import Modals, {
  modalOpen,
  modalClose,
  modalForceClose
} from '../reducers/Modals';
import {
  commentsLoadSelectAccount,
  commentsLoadPosts,
  commentsLoadSelectPost,
  commentsLoadStart,
  commentsLoadCheckLoop
} from '../reducers/CommentsLoad';
// Components
import Menu from '../components/Menu/Menu';
import ModalHelp from '../components/ModalHelp/ModalHelp';
import ModalAccountSelect from '../components/ModalAccountSelect/ModalAccountSelect';
import ModalPostSelect from '../components/ModalPostSelect/ModalPostSelect';
import ModalExportProgress from '../components/ModalExportProgress/ModalExportProgress';
class App extends Component {
  componentDidMount() {
    this.props.actionDialogsLoad();
    this.props.actionAccountsLoad();
  }
  createMenu(callbackModalOpen) {
    return <Menu 
      callbackButtonLoad={() => {callbackModalOpen(MODAL_ACCOUNT_SELECT)}}
      callbackButtonHelp={() => {callbackModalOpen(MODAL_HELP)}}
    />;
  }
  createModalHelp(callbackOpen, callbackClose) {
    return <ModalHelp 
      callbackOpen={() => callbackOpen(MODAL_ACCOUNT_SELECT)} 
      callbackClose={callbackClose} 
    />;
  }
  createModalAccountSelect(callbackOpen, callbackClose, callbackAccountSelect, callbackLoadPosts, accounts) {
    const commentLoadSelectAccount = (id) => {
      callbackAccountSelect(id);
      callbackLoadPosts(id);
      callbackOpen(MODAL_POST_SELECT);
    };
    return <ModalAccountSelect 
      callbackClose={callbackClose} 
      callbackAccountSelect={(id) => {commentLoadSelectAccount(id)}}
      accounts={accounts}
    />;
  }
  createModalPostSelect(callbackOpen, callbackClose, callbackSelectPost, callbackPostExportStart, callbackLoadCheckLoop, posts) {
    const startExport = (postId) => {
      callbackSelectPost(postId);
      callbackPostExportStart();
      callbackLoadCheckLoop();
      callbackOpen(MODAL_EXPORT_PROGRESS);
    };
    return <ModalPostSelect
      callbackClose={callbackClose} 
      callbackPostSelect={startExport}
      posts={posts}
    />;
  }
  createModalExportProgress(callbackClose, current, total, link) {
    return <ModalExportProgress 
      callbackClose={callbackClose}
      current={current}
      total={total}
      link={link}
    />;
  }
  render() {
    if (this.props.dialogs.status !== STATUS_OK)
      return null;
    return (
      <div style={{width: '1100px', height: '600px', margin: '0 auto', display: 'flex', flexDirection: 'column'}}>
        {this.createMenu(
          this.props.actionModalOpen
        )}
        <Dialogs 
          dialogs={this.props.dialogs}
          actionDialogSelect={this.props.actionDialogSelect}
          actionDialogMarkAsRead={this.props.actionDialogMarkAsRead}
          actionCommentSelect={this.props.actionCommentSelect}
          actionCommentDelete={this.props.actionCommentDelete}
          actionCommentAnswerEdit={this.props.actionCommentAnswerEdit}
          actionCommentAnswerSend={this.props.actionCommentAnswerSend}
        />
        { this.props.modals.current === MODAL_HELP && this.createModalHelp(
          this.props.actionModalOpen,
          this.props.actionModalClose
        ) }
        { this.props.modals.current === MODAL_ACCOUNT_SELECT && this.createModalAccountSelect(
          this.props.actionModalOpen,
          this.props.actionModalClose,
          this.props.actionCommentsLoadSelectAccount,
          this.props.actionCommentsLoadPosts,
          this.props.accounts.social
        ) }
        { this.props.modals.current === MODAL_POST_SELECT && this.createModalPostSelect(
          this.props.actionModalOpen,
          this.props.actionModalClose,
          this.props.actionCommentsLoadSelectPost,
          this.props.actionCommentsLoadStart,
          this.props.actionCommentsLoadCheckLoop,
          this.props.commentsLoad.posts
        ) }
        { this.props.modals.current === MODAL_EXPORT_PROGRESS && this.createModalExportProgress(
          this.props.actionModalForceClose,
          this.props.commentsLoad.exportCommentsCurrent,
          this.props.commentsLoad.exportCommentsTotal,
          this.props.commentsLoad.exportLink
        ) }
      </div>
    );
  }
}
function mapStateToProps(state) {
  return {
    dialogs: state.dialogs,
    modals: state.modals,
    accounts: state.accounts,
    commentsLoad: state.commentsLoad
  };
}
function mapDispatchToProps(dispatch, ownProps) {
  return {
    // Dialogs
    actionDialogsLoad: () => {
      dispatch(dialogsLoad());
    },
    actionDialogSelect: (postId) => {
      dispatch(dialogSelect(postId));
    },
    actionDialogMarkAsRead: (commentsIds) => {
      dispatch(dialogMarkAsRead(commentsIds));
    },
    actionCommentSelect: (commentsId) => {
      dispatch(commentSelect(commentsId));
    },
    actionCommentDelete: (postId, commentId) => {
      dispatch(commentDelete(postId, commentId));
    },
    actionCommentAnswerEdit: (commentId, text) => {
      dispatch(commentAnswerEdit(commentId, text));
    },
    actionCommentAnswerSend: (postId, commentId, text) => {
      dispatch(commentAnswerSend(postId, commentId, text));
    },
    // Modals
    actionModalOpen: (modalId) => {
      dispatch(modalOpen(modalId));
    },
    actionModalClose: () => {
      dispatch(modalClose());
    },
    actionModalForceClose: () => {
      dispatch(modalForceClose());
    },
    // Accounts
    actionAccountsLoad: () => {
      dispatch(accountsLoad());
    },
    // Comments Load
    actionCommentsLoadSelectAccount: (id) => {
      dispatch(commentsLoadSelectAccount(id));
    },
    actionCommentsLoadPosts: () => {
      dispatch(commentsLoadPosts());
    },
    actionCommentsLoadSelectPost: (id) => {
      dispatch(commentsLoadSelectPost(id));
    },
    actionCommentsLoadStart: () => {
      dispatch(commentsLoadStart());
    },
    actionCommentsLoadCheckLoop: () => {
      dispatch(commentsLoadCheckLoop());
    }
  };
}
export default connect(mapStateToProps, mapDispatchToProps)(App);
Answer 1

У вас все слеплено кучей иначе не сказать, могу лишь предложить свой примерный шаблон для React с Redux, ссылка на шаблон, если что-то не поймете, задавайте вопросы, надеюсь это вам поможет.

Примерно так выглядит мой шаблон:

  • actions
    • index.js
    • action1.js
    • action2.js
  • components
    • component1
      • Component1.js
      • Component1Container.js
      • style.css
    • component2
      • Component2.js
      • Component2Container.js
      • style.css
    • App.js
    • AppContainer.js
    • style.css
  • reducers
    • index.js
    • reducer1.js
    • reducer2.js
  • constants
    • index.js
  • index.js
Answer 2

У меня нет слишком много опыта в использовании модулей из реакции, но я ранее изучал работу в Butstrap и пришел использовать этот код для создания модулей. И использовать его как компонент ребенка, вызванного родительским командиром. Я могу отправить вам это, если вы ответите. Потому что ссылки CDN требуемых частей Butstrap должны использоваться в index.html. Поэтому его можно частично использовать и пропускать без установки в реактивных модулях и приложениях.

READ ALSO
Галерея magnific popup

Галерея magnific popup

На сайте есть слайдер, по клику открывается MFP-галерея со смешанными элементами, по наведению на картинку в слайдере, полноразмерное изображение...

277
Парсинг string в integer с комой [Jquery]

Парсинг string в integer с комой [Jquery]

Есть стринг который нужно перевести в значение, но хочу, что бы оно было с комой и желательно в переменнойКод написал для примера, поэтому...

212
Скриптинг в формах, JQuery API

Скриптинг в формах, JQuery API

Мне нужно реализовать HTML страницу, на которой необходимо отобразить ФормуЯ подключил проигрыватель форм, создал index

133