{"id":285411,"date":"2017-04-24T11:10:35","date_gmt":"2017-04-24T07:10:35","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=285411"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=285411","title":{"rendered":"\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043c\u043e\u0434\u0443\u043b\u044c\u043d\u044b\u0445 React + Redux \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 2. \u042f\u0434\u0440\u043e"},"content":{"rendered":"<p><a href=\"https:\/\/habrahabr.ru\/post\/326484\/\">\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438<\/a> \u044f \u0443\u0434\u0435\u043b\u0438\u043b \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0431\u0449\u0435\u0439 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438: \u0440\u0435\u0434\u044e\u0441\u0435\u0440\u044b, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0438 \u044d\u043a\u0448\u043d\u044b \u0447\u0430\u0449\u0435 \u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e, \u0430 \u043d\u0435 \u043f\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0438\u0445 \u0446\u0435\u043b\u0435\u0441\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u0435\u0435 \u043f\u043e \u043c\u043e\u0434\u0443\u043b\u044f\u043c, \u0430 \u043d\u0435 \u043f\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u043f\u0430\u043f\u043a\u0430\u043c <i>actions<\/i>, <i>components<\/i>, <i>reducers<\/i>. \u0422\u0430\u043a\u0436\u0435 \u043a \u043c\u043e\u0434\u0443\u043b\u044f\u043c \u0431\u044b\u043b\u0438 \u043f\u0440\u0435\u0434\u044a\u044f\u0432\u043b\u0435\u043d\u044b \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f:  <\/p>\n<ol>\n<li>\u0431\u044b\u0442\u044c \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u043c\u0438 \u0434\u0440\u0443\u0433 \u043e\u0442 \u0434\u0440\u0443\u0433\u0430<\/li>\n<li>\u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u0447\u0435\u0440\u0435\u0437 API \u044f\u0434\u0440\u0430<\/li>\n<\/ol>\n<p>  \u0412 \u044d\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u044f\u0434\u0440\u0430, \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0439 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 data-driven \u0441\u0438\u0441\u0442\u0435\u043c.<a name=\"habracut\"><\/a><br \/>  \u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0443\u043b\u044f. \u0420\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u0443\u0434\u043e\u0431\u043d\u043e. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u041e\u041e\u041f:  <\/p>\n<pre><code class=\"javascript\">class ModuleBase{   constructor(base){     this[_base] = base     this[_ref] = getRef(this)   }    \/**    * unique module id    * @returns {string}    *\/   get id(){     return this.constructor.name   }    \/**    * full module ref including all parents    * @returns {string}    *\/   get ref(){     return this[_ref]   }    \/**    * module title in navigation    * @returns {string}    *\/   get title(){     return this.id   }    \/**    * module group in navigation    * @returns {string}    *\/   get group(){     return null   }    \/**    * react component    * @returns {function}    *\/   get component() {     return null   }    \/**    * router route    * @return {object}    *\/   get route(){     return getRoute(this)   }    \/**    * router path    * @return {string}    *\/   get path(){     return this.id   }    \/**    * children modules    * @return {Array}    *\/   get children(){     return []   }    \/**    * @type {function}    *\/   reduce   \/\/.... }<\/code><\/pre>\n<blockquote><p>\u0412 \u043a\u043e\u0434\u0435 \u0432\u044b\u0448\u0435 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u044f\u0446\u0438\u0438 <a href=\"http:\/\/2ality.com\/2016\/01\/private-data-classes.html\">\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0441\u0438\u043c\u0432\u043e\u043b\u044b<\/a>.  <\/p><\/blockquote>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u043e \u2013 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 <code>ModuleBase<\/code>, \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0433\u0435\u0442\u0442\u0435\u0440\u044b \u0438 \u043f\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u044e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>reduce<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0440\u0435\u0434\u044e\u0441\u0435\u0440\u0430.<br \/>  \u0412 \u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u0440\u0430\u0437 \u043c\u044b \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u043b\u0438 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0432\u0442\u043e\u0440\u044b\u043c \u0443\u0440\u043e\u0432\u043d\u0435\u043c. \u0412 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u044d\u0442\u043e\u0433\u043e \u0431\u044b\u0432\u0430\u0435\u0442 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e. \u041a\u0440\u043e\u043c\u0435 \u044d\u0442\u043e\u0433\u043e \u0432 \u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u0440\u0430\u0437 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u043c\u0435\u0436\u0434\u0443 \u0440\u0435\u0434\u044e\u0441\u0435\u0440\u043e\u043c \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043c\u043e\u0434\u0443\u043b\u044f \u0438 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u0435\u0439 \u0440\u0435\u0434\u044e\u0441\u0435\u0440\u043e\u0432 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445. \u042d\u0442\u043e \u00ab\u043b\u043e\u043c\u0430\u0435\u0442\u00bb \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u044e. <br \/>  \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 CRUD \u043d\u0430\u0434 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c\u044e \u0432 \u0411\u0414 \u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0434\u0443\u043b\u0438 \u0442\u0430\u043a:  <\/p>\n<pre><code>\/SomeEntity   \/components     \/Master.js   \/children     \/index.js     \/create.js     \/update.js   \/index.js <\/code><\/pre>\n<p>  \u0421\u0447\u0438\u0442\u0430\u0435\u043c, \u0447\u0442\u043e \u0434\u043b\u044f <i>create<\/i> \u0438 <i>update<\/i> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0444\u043e\u0440\u043c\u044b, \u0430 \u0434\u043b\u044f \u0432\u044b\u0432\u043e\u0434\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 <code>Grid<\/code> \u0438\u0437 \u044f\u0434\u0440\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u043e\u0434\u0443\u043b\u0438 \u0434\u043b\u044f \u044d\u0442\u0438\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439.<br \/>  \u0420\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0432\u044b\u0432\u043e\u0434 \u043b\u0435\u0439\u0430\u0443\u0442\u0430, \u0441\u0441\u044b\u043b\u043e\u043a \u00ab\u0441\u043e\u0437\u0434\u0430\u0442\u044c\u00bb, \u00ab\u043d\u0430\u0437\u0430\u0434 \u043a \u0441\u043f\u0438\u0441\u043a\u0443\u00bb \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043e\u0431 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0441\u0442\u0438 \u0438\u043b\u0438 \u043d\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0441\u0442\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443. <code>Index<\/code> \u2013 \u0437\u0430 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044e, \u043f\u0430\u0433\u0438\u043d\u0430\u0446\u0438\u044e \u0438 \u0441\u0441\u044b\u043b\u043a\u0438. <code>Create<\/code> \u0438 <code>Update<\/code> \u0432\u044b\u0432\u043e\u0434\u044f\u0442 \u0444\u043e\u0440\u043c\u044b \u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435. <br \/>  \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0440\u0435\u0434\u044e\u0441\u0435\u0440 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043c\u043e\u0434\u0443\u043b\u044f \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u0435\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a\u043e \u0432\u0441\u0435\u043c\u0443 \u043f\u043e\u0434\u0433\u0440\u0430\u0444\u0443 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043c\u043e\u0434\u0443\u043b\u044f, \u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u2013 \u043a\u0430\u0436\u0434\u044b\u0439 \u043a \u0441\u0432\u043e\u0435\u0439 \u0447\u0430\u0441\u0442\u0438. \u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0434\u0432\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u043e\u0432\u043a\u0438<\/p>\n<h3>\u0414\u043b\u044f \u0440\u043e\u0443\u0442\u043e\u0432<\/h3>\n<p>  <\/p>\n<pre><code class=\"javascript\">const getRoute = module =&gt; {   const route = {     path: module.path,     title: module.title,     component: module.component   }    const children = module.children   if(children) {     ModuleBase.check(children)     const index = children.filter(x =&gt; x.id.endsWith(INDEX))     if(index.length &gt; 0){       \/\/ share title with parent module       route.indexRoute = {         component: index[0].component       }     }      route.childRoutes = module.children       .filter(x =&gt; !x.id.endsWith(INDEX))       .map(getRoute)   }    return route }<\/code><\/pre>\n<p>  <\/p>\n<h3>\u0418 \u0434\u043b\u044f \u0440\u0435\u044e\u0441\u0435\u0440\u043e\u0432<\/h3>\n<p>  <\/p>\n<pre><code class=\"javascript\">class ModuleBase{   \/\/....   combineReducers(){     const childrenMap = {}      let children = Array.isArray(this.children) ? this.children : []     ModuleBase.check(children)      const withReducers = children.filter(x =&gt; typeof(x.reduce) === 'function' || x.children.length &gt; 0)     for (let i = 0; i &lt; withReducers.length; i++) {       childrenMap[children[i].id] = children[i]     }      if(withReducers.length == 0){       return reducerOrDefault(this.reduce)     }      const reducers = {}     for(let i in childrenMap){       reducers[i] = childrenMap[i].combineReducers()     }      const parent = this     const reducer = typeof(this.reduce) === 'function'       ? (state, action) =&gt; {         if(!state){           state = parent.initialState         }          const nextState = parent.reduce(state, action)          if(typeof(nextState) !== 'object'){           throw Error(parent.id + '.reduce returned wrong value. Reducers must return plain objects')         }          for(let i in childrenMap){           if(!nextState[i]){             nextState[i] = childrenMap[i].initialState           }            nextState[i] = {...reducers[i](nextState[i], action)}           if(typeof(nextState[i]) !== 'object'){             throw Error(childrenMap[i].id + '.reduce returned wrong value. Reducers must return plain objects')           }         }          return {...nextState}       }       : combineReducers(reducers)       return reducer   }<\/code><\/pre>\n<p>  <\/p>\n<blockquote><p>\u042d\u0442\u043e \u043d\u0435 \u0441\u0430\u043c\u0430\u044f \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u0440\u0435\u0434\u044e\u0441\u0435\u0440\u0430. \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0434\u0430\u0436\u0435 \u043e\u043d\u0430 \u0437\u0430\u043d\u044f\u043b\u0430 \u0443 \u043c\u0435\u043d\u044f \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u0411\u0443\u0434\u0443 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u0435\u043d, \u0435\u0441\u043b\u0438 \u043a\u0442\u043e-\u0442\u043e \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u043f\u043e\u0434\u0441\u043a\u0430\u0436\u0435\u0442, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043b\u0443\u0447\u0448\u0435.<\/p><\/blockquote>\n<p>  <\/p>\n<h3>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435 \u0440\u043e\u0443\u0442\u043e\u0432 \u0438 \u0441\u0442\u0435\u0439\u0442\u0430<\/h3>\n<p>  \u0414\u0430\u043d\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043c\u043e\u0434\u0443\u043b\u044c\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435 \u0441\u0442\u0435\u0439\u0442\u0430 \u0438 \u0440\u043e\u0443\u0442\u043e\u0432 \u043e\u0434\u0438\u043d \u043a \u043e\u0434\u043d\u043e\u043c\u0443, \u0441 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f\u043c\u0438:  <\/p>\n<ol>\n<li><code>\/Update<\/code> \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0430 <code>\/:id<\/code><\/li>\n<li><code>\/Index<\/code> \u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f (\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <code>indexRoute<\/code>)<\/li>\n<li>\u0414\u043b\u044f <code>Delete<\/code> \u043d\u0435\u0442 \u0441\u0432\u043e\u0435\u0433\u043e \u0440\u043e\u0443\u0442\u0430. \u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0438\u0437 \u043c\u043e\u0434\u0443\u043b\u044f <code>Index<\/code><\/li>\n<\/ol>\n<p>  \u041c\u0435\u0442\u043e\u0434 path \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0438 \u0442\u043e\u0433\u0434\u0430 \u0440\u043e\u0443\u0442 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c \u043e\u0442 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u0434\u0443\u043b\u044f<br \/>  \u041c\u043e\u0436\u043d\u043e \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u043b\u044e\u0431\u043e\u0439 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u0438. \u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e, \u0435\u0441\u043b\u0438 \u0432 \u0432\u0430\u0448\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u0440\u043e\u0443\u0442 <code>\/<\/code>, \u0442\u043e \u0446\u0435\u043b\u0435\u0441\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043c\u043e\u0434\u0443\u043b\u044c <code>App<\/code> \u0438 \u0432\u043b\u043e\u0436\u0438\u0442\u044c \u0432 \u043d\u0435\u0433\u043e \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u043f\u043e\u0434\u0445\u043e\u0434 \u043f\u043e\u0432\u0441\u0435\u043c\u0435\u0441\u0442\u043d\u043e.  <\/p>\n<blockquote><p>\u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0432 \u0440\u0435\u0434\u044e\u0441\u0435\u0440\u0435 App (\u0435\u0441\u043b\u0438 \u0442\u0430\u043a\u043e\u0439 \u043d\u0443\u0436\u0435\u043d) \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u044b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043b\u044e\u0431\u043e\u0433\u043e \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u043c\u043e\u0434\u0443\u043b\u044f. \u041f\u043e\u0436\u0430\u043b\u0443\u0439, \u044d\u0442\u043e \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043a\u0440\u0443\u0442\u043e \u0434\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e, \u0434\u0430\u0436\u0435 \u0441\u0430\u043c\u043e\u0433\u043e \u043a\u0440\u0443\u0442\u043e\u0433\u043e \u0440\u0435\u0434\u044e\u0441\u0435\u0440\u0430. \u042f \u043d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0432\u043e\u043e\u0431\u0449\u0435 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c reduce \u0434\u043b\u044f \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043c\u043e\u0434\u0443\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041e\u0434\u043d\u0430\u043a\u043e, \u0442\u0430\u043a\u043e\u0439 \u0440\u0435\u0434\u044e\u0441\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u0435\u0437\u0435\u043d \u0434\u043b\u044f \u043a\u0430\u043a\u0438\u0445-\u0442\u043e \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439.<\/p><\/blockquote>\n<p>  \u0421 \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u043e\u043c \u043f\u043e\u043a\u043e\u043d\u0447\u0435\u043d\u043e, \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u00ab<a href=\"https:\/\/maxfarseer.gitbooks.io\/redux-course-ru\/content\/prisoedinenie_dannih_connect.html\">\u0437\u0430\u043a\u043e\u043d\u0435\u043a\u0442\u0438\u0442\u044c<\/a>\u00bb \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043a \u0441\u0442\u0435\u0439\u0442\u0443. \u0422\u0430\u043a \u043a\u0430\u043a \u0440\u0435\u0434\u044e\u0441\u0435\u0440\u044b \u0441\u043a\u043e\u043c\u043f\u043e\u043d\u043e\u0432\u0430\u043d\u044b \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435 \u0441\u043e \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u044c\u044e \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u0438\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u0442\u0430\u043a\u0436\u0435. \u0417\u0434\u0435\u0441\u044c \u0432\u0441\u0435 \u043f\u0440\u043e\u0441\u0442\u043e. \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e <code>mapDispatchToProp<\/code>s \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0447\u0443\u0442\u044c \u043d\u0438\u0436\u0435.<\/p>\n<h3>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u044f\u0434\u0440\u0430<\/h3>\n<p>  \u0418\u0442\u0430\u043a, <code>ModuleBase<\/code>\u2013 \u043f\u0435\u0440\u0432\u0430\u044f \u0438 \u043d\u0435\u043e\u0442\u044a\u0435\u043c\u043b\u0435\u043c\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u044f\u0434\u0440\u0430. \u0411\u0435\u0437 \u043d\u0435\u0433\u043e \u0441\u0432\u043e\u0439 \u043a\u043e\u0434 \u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u043f\u043e\u0434\u0446\u0435\u043f\u0438\u0442\u044c. <code>ModuleBase<\/code> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 API:  <\/p>\n<ol>\n<li>\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0432 \u0440\u043e\u0443\u0442\u0435\u0440\u0435<\/li>\n<li>\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0440\u0435\u0434\u044e\u0441\u0435\u0440\u0430 \u043c\u043e\u0434\u0443\u043b\u044f<\/li>\n<li>Connect \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043a \u0441\u0442\u0435\u0439\u0442\u0443 redux<\/li>\n<\/ol>\n<p>  \u041d\u0435 \u043f\u043b\u043e\u0445\u043e, \u043d\u043e \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e. <code>CRUD<\/code> \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e. \u0414\u043e\u0431\u0430\u0432\u0438\u043c <code>DataGridModuleBase<\/code> \u0438 <code>FormModuleBase<\/code>. \u0414\u043e \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043c\u044b \u043d\u0435 \u0443\u0442\u043e\u0447\u043d\u044f\u043b\u0438 \u043a\u0430\u043a\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0432 \u043c\u043e\u0434\u0443\u043b\u044f\u0445. <\/p>\n<h3>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b<\/h3>\n<p>  <a href=\"https:\/\/medium.com\/@learnreact\/container-components-c0e67432e005\">\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b<\/a> \u2013 \u043e\u0434\u0438\u043d \u0438\u0437 \u0448\u0438\u0440\u043e\u043a\u043e \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0445 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u043e\u0432 \u0432 React. \u0415\u0441\u043b\u0438 \u043a\u043e\u0440\u043e\u0442\u043a\u043e, \u0442\u043e \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438 \u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u043c\u0438 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c:  <\/p>\n<ol>\n<li>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b (\u0438\u043b\u0438 \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b) \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0438 \u043b\u043e\u0433\u0438\u043a\u0438<\/li>\n<li>\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b (\u043a\u0430\u043a \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0438\u0437 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f) \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u044e\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044f \u0431\u0430\u0439\u043d\u0434\u0438\u043d\u0433 \u043c\u0435\u0436\u0434\u0443 \u0432\u043d\u0435\u0448\u043d\u0438\u043c \u043c\u0438\u0440\u043e\u043c \u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438<\/li>\n<\/ol>\n<p>  \u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b (\u043a\u0430\u043a \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0438\u0437 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f) \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u044e\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044f \u0431\u0430\u0439\u043d\u0434\u0438\u043d\u0433 \u043c\u0435\u0436\u0434\u0443 \u0432\u043d\u0435\u0448\u043d\u0438\u043c \u043c\u0438\u0440\u043e\u043c \u0438 \u0441\u043b\u043e\u0435\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f.<br \/>  \u0422\u0430\u043a\u0430\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u0443\u043b\u0443\u0447\u0448\u0430\u0435\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0434\u0430, \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u043c\u0435\u0436\u0434\u0443 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u0430\u043c\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435. \u0424\u0443\u043d\u043a\u0446\u0438\u044f <a href=\"https:\/\/maxfarseer.gitbooks.io\/redux-course-ru\/content\/prisoedinenie_dannih_connect.html\">connect<\/a> \u043f\u043e \u0441\u0443\u0442\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0444\u0430\u0431\u0440\u0438\u043a\u043e\u0439 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432.<br \/>  \u0414\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 <code>DataGridModule<\/code> \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f:  <\/p>\n<ol>\n<li><i>\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442<\/i> <code>DataGrid<\/code><\/li>\n<li>\u0435\u0433\u043e <i>\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440<\/i> <code>DataGridContainer<\/code><\/li>\n<li>\u0440\u0435\u0434\u044e\u0441\u0435\u0440 \u0434\u043b\u044f \u0441\u0432\u044f\u0437\u0438 \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u043c \u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 redux<\/li>\n<\/ol>\n<p>  \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u044f \u043e\u043f\u0443\u0441\u043a\u0430\u044e. \u0414\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0441\u0442\u0435\u0439\u0442\u0443 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>ModuleBase.connect<\/code>. \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u041c\u043e\u0436\u043d\u043e \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0433\u0440\u0438\u0434 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0438 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c <code>componentDidMount <\/code> \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430. \u041f\u043e\u0434\u0445\u043e\u0434, \u0432 \u0446\u0435\u043b\u043e\u043c, \u0440\u0430\u0431\u043e\u0447\u0438\u0439, \u043d\u043e \u0438\u043c\u0435\u044e\u0449\u0438\u0439 \u0434\u0432\u0430 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0430:  <\/p>\n<ol>\n<li>\u0433\u0438\u0433\u0430\u043d\u0442\u0441\u043a\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e boilerplate \u0438 \u043a\u043e\u043f\u0438\u043f\u0430\u0441\u0442\u044b. \u0410 \u043a\u043e\u043f\u0438-\u043f\u0435\u0439\u0441\u0442, \u043a\u0430\u043a \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e, \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u043e\u0448\u0438\u0431\u043a\u0430\u043c<\/li>\n<li>\u043d\u0438\u0437\u043a\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 (\u044f\u0434\u0440\u043e \u043f\u043e\u043a\u0430 \u043d\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e API \u0434\u043b\u044f \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u044d\u0442\u043e \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e)<\/li>\n<\/ol>\n<h3>\u041f\u0440\u0438\u043c\u0435\u0441\u0438 (mixin)<\/h3>\n<p>  \u0420\u0430\u0441\u0448\u0438\u0440\u0438\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u043e\u0432\u043a\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e mixin\u2019\u043e\u0432. <code>class<\/code> \u0438 <code>extends<\/code> \u2013 \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0432 ES6. \u0418\u043d\u044b\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u0437\u0430\u043f\u0438\u0441\u044c <code>const Enhanced = superclass =&gt; class extends superclass<\/code> \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u0430. \u042d\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f JavaScript, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u043d\u0430 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0430\u0445.<br \/>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u044f\u0434\u0440\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044e <a href=\"http:\/\/justinfagnani.com\/2015\/12\/21\/real-mixins-with-javascript-classes\/\">mix<\/a> \u0438 \u043f\u0440\u0438\u043c\u0435\u0441\u0438 <code>Preloader<\/code> \u0438 <code>ServerData<\/code>:  <\/p>\n<pre><code class=\"javascript\">const Preloader = Component =&gt; class extends Component {   render() {     const propsToCheck = subset(this.props, this.constructor.initialState)     let isInitialized = true     let isFetching = false      for(let i in propsToCheck){         if(typeof(propsToCheck[i][IS_FETCHING]) === 'boolean'){           if(!isFetching && propsToCheck[i][IS_FETCHING]){             isFetching = true           }            \/\/ if something except &quot;isFetching&quot; presents it's initialized           if(isInitialized && Object.keys(propsToCheck[i]).length === 1){             isInitialized = false           }         }     }      return isInitialized       ? (&lt;Dimmer.Dimmable dimmed={isFetching}&gt;         &lt;Dimmer active={isFetching} inverted&gt;           &lt;Loader \/&gt;         &lt;\/Dimmer&gt;         {super.render()}       &lt;\/Dimmer.Dimmable&gt;)       : (&lt;Dimmer.Dimmable dimmed={true}&gt;         &lt;Dimmer active={true} inverted&gt;           &lt;Loader \/&gt;         &lt;\/Dimmer&gt;         &lt;div style={divStyle}&gt;&lt;\/div&gt;       &lt;\/Dimmer.Dimmable&gt;)   } }  const ServerData = superclass =&gt; class extends mix(superclass).with(Preloader) {   componentDidMount() {     this.props.queryFor(       this.props.params,       subset(this.props, this.constructor.initialState))   }<\/code><\/pre>\n<p>  \u041f\u0435\u0440\u0432\u044b\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0432\u0441\u0435 \u043a\u043b\u044e\u0447\u0438 \u0432 \u0441\u0442\u0435\u0439\u0442\u0435 \u0438 \u0435\u0441\u043b\u0438 \u043d\u0430\u0445\u043e\u0434\u0438\u0442 \u0445\u043e\u0442\u044f-\u0431\u044b \u043e\u0434\u0438\u043d \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e\u043c <code>isFetching: true<\/code> \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u043f\u043e\u0432\u0435\u0440\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0434\u0438\u043c\u043c\u0435\u0440. \u0415\u0441\u043b\u0438 \u043a\u0440\u043e\u043c\u0435 <code>isFetching<\/code> \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043d\u0435\u0442, \u0441\u0447\u0438\u0442\u0430\u0435\u043c, \u0447\u0442\u043e \u043e\u043d\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u0440\u0438\u0439\u0442\u0438 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 (\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u043d\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c).<br \/>  \u041c\u0438\u043a\u0441\u0438\u043d <code>ServerData<\/code> \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u043e\u0434\u043c\u0435\u0448\u0438\u0432\u0430\u0435\u0442 \u043f\u0440\u0435\u043b\u043e\u0430\u0434\u0435\u0440 \u0438 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 <code>componentDidMount<\/code>.<\/p>\n<h3>queryFor<\/h3>\n<p>  \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e queryFor. \u0415\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u043b <code>Module.connect<\/code> \u0447\u0435\u0440\u0435\u0437 <code>mapDispatchToProps<\/code>.  <\/p>\n<pre><code class=\"javascript\">export const queryFactory = dispatch =&gt; {   if(typeof (dispatch) != 'function'){     throw new Error('dispatch is not a function')   }    return (moduleId, url, params = undefined) =&gt; {     dispatch({       type: combinePath(moduleId, GET),       params     })      return new Promise(resolve =&gt; {       dispatch(function () {         get(url, params).then(response =&gt; {           const error = 'ok' in response && !response.ok           const data = error             ? {ok: response.ok, status: response.status}             : response            dispatch({             type: combinePath(moduleId, GET + (error ? FAILED : SUCCEEDED)),             ...data           })            resolve(data)         })       })     })   } }  export const queryAll = (dispatch, moduleRef, params, ...keys) =&gt; {   const query = queryFactory(dispatch)   if(!keys.length){     throw new Error('keys array must be not empty')   }    const action = combinePath(moduleRef, keys[0])   let promise = query(action, fixPath(action), params)   for(let i = 1; i &lt; keys.length; i++){     promise.then(() =&gt; {       let act = combinePath(moduleRef, keys[i])       query(act, fixPath(act), params)     })   } }  export const queryFor = (dispatch, moduleRef, params, state) =&gt; {   const keys = []    for (let i in state) {     if (state[i].isFetching !== undefined) {       keys.push(toUpperCamelCase(i))     }   }    return queryAll(dispatch, moduleRef, params, ...keys) <\/code><\/pre>\n<p>  \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>queryFactory<\/code> \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>query<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u0435\u043b\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440, \u0434\u0438\u0441\u043f\u0430\u0442\u0447\u0438\u0442 \u0432 <code>store<\/code> \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 <a href=\"https:\/\/developer.mozilla.org\/ru\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Promise\">promise<\/a>, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0432\u044b\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>queryAll<\/code>, \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043f\u0435\u0440\u0435\u0434\u0430\u0441\u0442 \u0442\u0430 \u0441\u0430\u043c\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>queryFor<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 <code>isFetching<\/code> \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u0435 <s>\u0432 \u0434\u043e\u043c\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u043b \u0414\u0436\u0435\u043a<\/s>.<br \/>  \u0414\u043e\u043f\u0438\u0448\u0435\u043c \u00ab\u043e\u0431\u043e\u0433\u043e\u0449\u0430\u043b\u043a\u0443\u00bb \u0434\u043b\u044f \u0441\u0442\u0435\u0439\u0442\u0430, \u0442\u0440\u0435\u0431\u0443\u044e\u0449\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445:  <\/p>\n<pre><code class=\"javascript\">ServerData.fromServer = (initialState, ...keys) =&gt; {   for(let i = 0; i &lt; keys.length; i++){     initialState[keys[i]].isFetching = false   }    return initialState }<\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0437\u043d\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u0438\u043a\u0441\u0438\u043d\u0430, \u0447\u0442\u043e\u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0438\u0437 \u043b\u044e\u0431\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0435\u0433\u043e \u0441 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439. \u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c initialState \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c mixin.<br \/>  \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0441\u0442\u0430\u0440\u0442\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445, \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0438 \u043e\u0448\u0438\u0431\u043e\u043a \u0438 \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u043f\u0438\u0448\u0435\u043c \u0440\u0435\u0434\u044e\u0441\u0435\u0440 \u0432 \u043c\u043e\u0434\u0443\u043b\u0435.<\/p>\n<h3>ServerData.reducerFor<\/h3>\n<p>  <\/p>\n<pre><code class=\"javascript\">ServerData.reducerFor = (moduleRef, initialState, next = null, method = GET) =&gt; {   if(!moduleRef){     throw Error('You must provide valid module name')   }    if(!initialState){     throw Error('You must provide valid initialState')   }    const reducer = {}    for (let i in initialState) {     reducer[i] = hasFetching(initialState, i)       ? ServerData.serverRequestReducerFactory(combinePath(moduleRef, i), initialState[i], next, method)       : passThrough(initialState[i])   }    if(Object.keys(reducer) &lt; 1){     throw Error('No &quot;isFetching&quot; found. Cannot build reducer')   }    const combined = combineReducers(reducer)   return combined }  export default class DataGridModuleBase extends ModuleBase {   constructor(base){     super(base)     \/\/ Create is required due to children module     this.reduce = ServerData.reducerFor(this.ref, DataGridContainer.initialState)   }    get component () {     return this.connect(DataGridContainer)   } } <\/code><\/pre>\n<h3>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043c\u043e\u0434\u0443\u043b\u044c \u0441 \u0433\u0440\u0438\u0434\u043e\u043c \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/h3>\n<p>  <\/p>\n<pre><code class=\"javascript\">export default class SomeEntityGrid extends DataGridModuleBase { }  export default class App extends ModuleBase{   constructor(base){     super(base)     this[_children] = [new SomeEntityGrid(this)]   }    get path (){     return '\/'   }    get component () {     return AppComponent   }    get children(){     return this[_children]   }<\/code><\/pre>\n<p>  <\/p>\n<blockquote><p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0434\u043e\u0447\u0438\u0442\u0430\u043b\u0438 \u0434\u043e \u043a\u043e\u043d\u0446\u0430, \u0442\u043e FromModuleBase \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438.<\/p><\/blockquote>\n<p>  <\/p>\n<h3>\u0424\u0438\u043d\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u044f\u0434\u0440\u0430<\/h3>\n<p>  <\/p>\n<pre><code>\/core   \/ModuleBase.js   \/api.js   \/components   \/containers   \/modules   \/mixins<\/code><\/pre>\n<p>  <\/p>\n<ol>\n<li>\u0411\u0430\u0437\u043e\u0432\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e-\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0438 \u043d\u0430\u0431\u043e\u0440\u044b \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432, \u0447\u0430\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0432\u043c\u0435\u0441\u0442\u0435 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>CRUD<\/code>).<\/li>\n<li>\u041f\u0430\u043f\u043a\u0438 <code>components<\/code> \u0438 <code>containers<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0447\u0430\u0441\u0442\u043e-\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e.<\/li>\n<li>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0440\u0438\u043c\u0435\u0441\u0435\u0439 \u043c\u043e\u0436\u043d\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b: \u0433\u0440\u0438\u0434 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u0433\u0440\u0438\u0434 \u0441 \u0438\u043d\u043b\u0430\u0439\u043d-\u0432\u0432\u043e\u0434\u043e\u043c, \u0433\u0440\u0438\u0434 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438 \u0438\u043d\u043b\u0430\u0439\u043d-\u0432\u0432\u043e\u0434\u043e\u043c \u0438 \u0442.\u0434.<\/li>\n<li>api.js \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c: fetch, get, post, put, del,\u2026 <\/li>\n<\/ol>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habrahabr.ru\/post\/327196\/\"> https:\/\/habrahabr.ru\/post\/327196\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p><a href=\"https:\/\/habrahabr.ru\/post\/326484\/\">\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438<\/a> \u044f \u0443\u0434\u0435\u043b\u0438\u043b \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0431\u0449\u0435\u0439 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438: \u0440\u0435\u0434\u044e\u0441\u0435\u0440\u044b, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0438 \u044d\u043a\u0448\u043d\u044b \u0447\u0430\u0449\u0435 \u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e, \u0430 \u043d\u0435 \u043f\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0438\u0445 \u0446\u0435\u043b\u0435\u0441\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u0435\u0435 \u043f\u043e \u043c\u043e\u0434\u0443\u043b\u044f\u043c, \u0430 \u043d\u0435 \u043f\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u043f\u0430\u043f\u043a\u0430\u043c <i>actions<\/i>, <i>components<\/i>, <i>reducers<\/i>. \u0422\u0430\u043a\u0436\u0435 \u043a \u043c\u043e\u0434\u0443\u043b\u044f\u043c \u0431\u044b\u043b\u0438 \u043f\u0440\u0435\u0434\u044a\u044f\u0432\u043b\u0435\u043d\u044b \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f:  <\/p>\n<ol>\n<li>\u0431\u044b\u0442\u044c \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u043c\u0438 \u0434\u0440\u0443\u0433 \u043e\u0442 \u0434\u0440\u0443\u0433\u0430<\/li>\n<li>\u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u0447\u0435\u0440\u0435\u0437 API \u044f\u0434\u0440\u0430<\/li>\n<\/ol>\n<p>  \u0412 \u044d\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u044f\u0434\u0440\u0430, \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0439 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 data-driven \u0441\u0438\u0441\u0442\u0435\u043c.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-285411","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/285411","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=285411"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/285411\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=285411"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=285411"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=285411"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}