
ã¯ããã«
Learning Reactã®ããŒã3ãžããããã ä»æ¥ã¯ãFacebook Fluxã¢ãŒããã¯ãã£ãã©ã®ããã«æ©èœãããããžã§ã¯ãã§ã©ã®ããã«äœ¿çšããããåŠã³ãŸãã
ãŸãããã®ã·ãªãŒãºã®æåã®2ã€ã®èšäºã ãGetting StartedïŒConceptsãããã³ã Node and Reactã䜿çšãããªã¢ã«ã¿ã€ã Twitterã¹ããªãŒã ã®æ§ç¯ ããèªãããšããå§ãããŸãã ããããèªãããšã¯ãªãã·ã§ã³ã§ãããReact.jsã«æ £ããŠããªãå Žåã¯ããã®èšäºãç解ããã®ã«åœ¹ç«ã¡ãŸãã
Fluxãšã¯äœã§ããïŒ
Fluxã¯ãFacebookããŒã ãReactã§äœæ¥ãããšãã«äœ¿çšããã¢ãŒããã¯ãã£ã§ãã ããã¯ãã¬ãŒã ã¯ãŒã¯ãã©ã€ãã©ãªã§ã¯ãªããReactãšåæ¹åããŒã¿ãããŒã®åçãè£å®ããæ°ããã¢ãŒããã¯ãã£ã¢ãããŒãã§ãã
ãã ããFacebookã¯Dispatcherå®è£ ãå«ããªããžããªãæäŸããŸã ã ãã£ã¹ãããã£ãŒã¯ãPublisher-Subscriberãã³ãã¬ãŒãïŒPub / subïŒã§ã°ããŒãã«ãªä»²ä»åœ¹ã®åœ¹å²ãæãããç»é²æžã¿ã®ãã³ãã©ãŒã«ãã€ããŒããéä¿¡ããŸãã
Fluxã¢ãŒããã¯ãã£ã®å žåçãªå®è£ ã§ã¯ããã®ã©ã€ãã©ãªãNodeJSã®EventEmitterã¯ã©ã¹ãšçµã¿åãããŠäœ¿çšââããŠãã¢ããªã±ãŒã·ã§ã³ã®ç¶æ ãå¶åŸ¡ã§ããã€ãã³ãæåã·ã¹ãã ãæ§ç¯ã§ããŸãã
Fluxã¯ããã®æ§æèŠçŽ ã«åºã¥ããŠèª¬æããã®ãããããæãç°¡åã§ãã
- ã¢ã¯ã·ã§ã³-Dispatcherãžã®ããŒã¿è»¢éãç°¡çŽ åãããã«ããŒ
- ãã£ã¹ãããã£ãŒ-ã¢ã¯ã·ã§ã³ãåãå ¥ããç»é²ããããã³ãã©ãŒã«è² è·ãåæ£ããŸã
- ã¹ãã¢/ã¹ãã¬ãŒãž-Managerã«ç»é²ããããã³ãã©ãŒã®ã¢ããªã±ãŒã·ã§ã³ã¹ããŒã¿ã¹ãšããžãã¹ããžãã¯ã®ã³ã³ãããŒ
- ã³ã³ãããŒã©ãŒãã¥ãŒ-ã¹ãã¢ã®ç¶æ ãåéããããããã£ãä»ããŠåã³ã³ããŒãã³ãã«æž¡ãReactã³ã³ããŒãã³ã
ãã®ããã»ã¹ãå³ã®ããã«ãªãæ§åãèŠãŠã¿ãŸãããã

APIã¯ããã«ã©ã®ããã«é¢ä¿ããŸããïŒ
ç§ã®æèŠã§ã¯ãFluxã¹ããªãŒã ãä»ããŠããŒã¿ãWarehouseã«è»¢éããã¢ã¯ã·ã§ã³ã䜿çšããããšã¯ãããã°ã©ã ã®å€éšããéä¿¡ãããããŒã¿ãå€éšã«éä¿¡ãããããŒã¿ãåŠçããæãç°¡åãªæ¹æ³ã§ãã
ãã£ã¹ãããã£ãŒ
ãã£ã¹ãããã£ãŒãšã¯äœã§ããïŒ
æ¬è³ªçã«ãDispatcherã¯ãã®ããã»ã¹å šäœã®ãããŒãžã£ãŒã§ãã ããã¯ãã¢ããªã±ãŒã·ã§ã³ã®äžå¿çãªããã§ãã ãã£ã¹ãããã£ãŒã¯ã¢ã¯ã·ã§ã³ãåä¿¡ãããããã®ã¢ã¯ã·ã§ã³ïŒããã³é¢é£ããŒã¿ïŒãç»é²æžã¿ãã³ãã©ãŒã«éä¿¡ããŸãã
ããã¯æ¬åœã«ãã/ãµãã§ããïŒ
ããã§ããªãã ãã£ã¹ãããã£ã¯ãç»é²ãããŠãããã¹ãŠã®ãã³ãã©ã«ããŒã¿ãéä¿¡ããç¹å®ã®é åºã§ãã³ãã©ãåŒã³åºãããšãã§ããŸããäœæ¥ãç¶è¡ããåã«æŽæ°ãåŸ ã€ããšãã§ããŸãã Dispatcherã¯1ã€ã ãã§ãã¢ããªã±ãŒã·ã§ã³å šäœã®äžå¿çãªãããšããŠæ©èœããŸãã
å€èŠ³ã¯æ¬¡ã®ãšããã§ãã
var Dispatcher = require('flux').Dispatcher; var AppDispatcher = new Dispatcher(); AppDispatcher.handleViewAction = function(action) { this.dispatch({ source: 'VIEW_ACTION', action: action }); } module.exports = AppDispatcher;
äžèšã®äŸã§ã¯ãManagerã®ã€ã³ã¹ã¿ã³ã¹ãšhandleViewActionã¡ãœãããäœæããŸãã ãã®æœè±¡åã¯ãã€ã³ã¿ãŒãã§ã€ã¹ã§äœæãããã¢ã¯ã·ã§ã³ãšãµãŒããŒ/ APIããã®ã¢ã¯ã·ã§ã³ãåé¢ããå Žåã«åœ¹ç«ã¡ãŸãã
ãã®ã¡ãœããã¯ããã§ã«ç»é²ãããŠãããã¹ãŠã®ãã³ãã©ãŒã«ã¢ã¯ã·ã§ã³ããŒã¿ãéä¿¡ãããã£ã¹ãããã¡ãœãããåŒã³åºããŸãã ãã®åŸããã®ã¢ã¯ã·ã§ã³ã¯ãªããžããªã«ãã£ãŠåŠçããããã®çµæãã¢ããªã±ãŒã·ã§ã³ã®ç¶æ ãæŽæ°ãããŸãã
次ã®å³ã¯ããã®ããã»ã¹ã瀺ããŠããŸãã

äŸåé¢ä¿
説æãããŠããDispatcherå®è£ ã®åªãã詳现ã®1ã€ã¯ãäŸåé¢ä¿ãèšè¿°ãããŠã§ã¢ããŠã¹å ã®ãã³ãã©ãŒã®å®è¡é åºãå¶åŸ¡ããæ©èœã§ãã ãããã£ãŠãç¶æ ãæ£ãã衚瀺ããããã«ãã¢ããªã±ãŒã·ã§ã³ã³ã³ããŒãã³ãã®1ã€ãä»ã®ã³ã³ããŒãã³ãã«äŸåããŠããå Žåããã®åã«æŽæ°ããå¿ èŠããããããWaitFor Dispatcherã¡ãœããã圹ç«ã¡ãŸãã
ãã®æ©èœã䜿çšããã«ã¯ãManagerã®ç»é²ã¡ãœããããè¿ãããå€ãã以äžã«ç€ºãããã«ãStoreã®dispatcherIndexããããã£ã«ä¿åããå¿ èŠããããŸãã
ShoeStore.dispatcherIndex = AppDispatcher.register(function(payload) { });
次ã«ãã¹ãã¬ãŒãžã§ã¢ã¯ã·ã§ã³ãåŠçãããšãã«ããã£ã¹ãããã£ã®waitForã¡ãœããã䜿çšããŠããã®æç¹ã§ShoeStoreããã§ã«ã¢ã¯ã·ã§ã³ãåŠçããŠããŒã¿ãæŽæ°ããŠããããšã確èªã§ããŸãã
case 'BUY_SHOES': AppDispatcher.waitFor([ ShoeStore.dispatcherIndex ], function() { CheckoutStore.purchaseShoes(ShoeStore.getSelectedShoes()); }); break;
ã泚æ transãïŒKen Wheelerã¯æããã«ãDispatcherã®æ代é ãã®å®è£ ã«ã€ããŠèª¬æããŠããŸããããã¯ãçŸåšã®ããŒãžã§ã³ã§ã¯waitForã¡ãœããã®çœ²åãç°ãªãããã§ãã
åºè/ä¿ç®¡
Fluxã®Vaultã¯ãã¢ããªã±ãŒã·ã§ã³ã®ãµããžã§ã¯ãé åã®ç¹å®ã®éšåã®ç¶æ ãå¶åŸ¡ããŸãã ããé«ãã¬ãã«ã§ã¯ãããã¯ããŠã§ã¢ããŠã¹ãããŒã¿ããã®ããŒã¿ãååŸããããã®ã¡ãœãããããã³ãããŒãžã£ãŒã«ç»é²ãããã¢ã¯ã·ã§ã³ãã³ãã©ãŒãæ ŒçŽããããšãæå³ããŸãã
ç°¡åãªãªããžããªãèŠãŠã¿ãŸãããã
var AppDispatcher = require('../dispatcher/AppDispatcher'); var ShoeConstants = require('../constants/ShoeConstants'); var EventEmitter = require('events').EventEmitter; var merge = require('react/lib/merge'); // shoes var _shoes = {}; // shoes function loadShoes(data) { _shoes = data.shoes; } // Event Emitter Node var ShoeStore = merge(EventEmitter.prototype, { // shoes getShoes: function() { return _shoes; }, emitChange: function() { this.emit('change'); }, addChangeListener: function(callback) { this.on('change', callback); }, removeChangeListener: function(callback) { this.removeListener('change', callback); } }); // AppDispatcher.register(function(payload) { var action = payload.action; var text; // switch(action.actionType) { case ShoeConstants.LOAD_SHOES: // loadShoes(action.data); break; default: return true; } // , "change" ShoeStore.emitChange(); return true; }); module.exports = ShoeStore;
äžèšã®äŸã§è¡ã£ãæãéèŠãªããšã¯ãNodeJSãããªããžããªã«EventEmitteræ©èœãè¿œå ããããšã§ããã ããã«ããããªããžããªã¯ã€ãã³ãããªãã¹ã³ããã³ãããŒããã£ã¹ãã§ããŸããããã«ããããããã®ã€ãã³ãããéå§ããŠããã¥ãŒã®ã³ã³ããŒãã³ããæŽæ°ã§ããŸãã ãã¥ãŒã¯ãªããžããªã«ãã£ãŠäœæããããå€æŽãã€ãã³ãããªãã¹ã³ãããããã¢ããªã±ãŒã·ã§ã³ã®ç¶æ ãå€æŽãããããšãåŠç¿ããçŸåšã®ç¶æ ãååŸïŒããã³è¡šç€ºïŒããæéã§ãã
ãŸããregisterã¡ãœããã䜿çšããŠãAppDispatcherã«ãã³ãã©ãŒãç»é²ããŸããã ããã¯ããªããžããªãAppDispatcherããã®ã¢ã©ãŒãããªãã¹ã³ããããã«ãªã£ãããšãæå³ããŸãã åä¿¡ããããŒã¿ã«åºã¥ããŠãswitchã¹ããŒãã¡ã³ãã¯ã¢ã¯ã·ã§ã³ãåŠçã§ãããã©ããã決å®ããŸãã ã¢ã¯ã·ã§ã³ãåŠçãããå Žåããå€æŽãã€ãã³ããçæããããã®ã€ãã³ãã«ãµãã¹ã¯ã©ã€ãããŠãããã¥ãŒã¯ãç¶æ ãæŽæ°ããããšã§ããã«å¿çããŸãã

ãã¥ãŒã¯ãRepositoryã€ã³ã¿ãŒãã§ã€ã¹ã®getShoesã¡ãœããã䜿çšããŠã_shoeså éšãªããžã§ã¯ããããã¹ãŠã®éŽãååŸãããã®ããŒã¿ãã³ã³ããŒãã³ãã«æž¡ããŸãã ããã¯éåžžã«åçŽãªäŸã§ããããã®ã¢ãŒããã¯ãã£ã«ããããã¥ãŒã®ä»£ããã«ããè€éãªããžãã¯ã䜿çšãããå Žåã§ããã³ã³ããŒãã³ããããªããããã«ä¿ã€ããšãã§ããŸãã
ã¢ã¯ã·ã§ã³ã¯ãªãšãŒã¿ãŒïŒã¢ã¯ã·ã§ã³/ã¢ã¯ã·ã§ã³ãã¡ã¯ããªãŒ
ã¢ã¯ã·ã§ã³ãã¡ã¯ããªã¯ããã¥ãŒããïŒãŸãã¯ä»ã®å ŽæããïŒåŒã³åºãããŠã¢ã¯ã·ã§ã³ããã£ã¹ãããã£ã«éä¿¡ããäžé£ã®ã¡ãœããã§ãã ã¢ã¯ã·ã§ã³ã¯ãDispatcherããµãã¹ã¯ã©ã€ããŒã«éä¿¡ãããã€ããŒãã§ãã
Facebookã®å®è£ ã§ã¯ãã¢ã¯ã·ã§ã³ã¯ã¿ã€ããç°ãªããŸããã¢ã¯ã·ã§ã³ããŒã¿ãšå ±ã«éä¿¡ãããå®æ°ã§ãã ã¿ã€ãã«ãã£ãŠã¯ãç»é²æžã¿ã®ãã³ãã©ãŒã§ã¢ã¯ã·ã§ã³ãé©åã«åŠçã§ããŸããããããã®ã¢ã¯ã·ã§ã³ããã®ããŒã¿ã¯å éšã¡ãœããã®åŒæ°ãšããŠäœ¿çšãããŸãã
const宣èšã¯æ¬¡ã®ããã«ãªããŸãã
var keyMirror = require('react/lib/keyMirror'); module.exports = keyMirror({ LOAD_SHOES: null });
äžèšã§ã¯ãReact keyMirrorã©ã€ãã©ãªã䜿çšããŠããæ³åã®ãšãããããŒãšåãå€ãæã€ãªããžã§ã¯ããäœæããŸããã ãã®ãã¡ã€ã«ãèŠãã ãã§ãã¢ããªã±ãŒã·ã§ã³ãéŽãããŒãã§ãããšèšããŸãã å®æ°ã䜿çšãããšããã¹ãŠãåçåããã¢ããªã±ãŒã·ã§ã³ã®æ©èœããã°ããè©äŸ¡ã§ããŸãã
次ã«ã察å¿ããã¢ã¯ã·ã§ã³ãã¡ã¯ããªã®çºè¡šãèŠãŠã¿ãŸãããã
var AppDispatcher = require('../dispatcher/AppDispatcher'); var ShoeStoreConstants = require('../constants/ShoeStoreConstants'); var ShoeStoreActions = { loadShoes: function(data) { AppDispatcher.handleAction({ actionType: ShoeStoreConstants.LOAD_SHOES, data: data }) } }; module.exports = ShoeStoreActions;
äžã®äŸã§ã¯ãæå®ããããŒã¿ãDispatcherã«æž¡ãã¡ãœãããShoeStoreActionsãªããžã§ã¯ãã«äœæããŸããã ããã§ãAPIïŒãŸãã¯ãããšãã°ãViewsïŒãããã®ãã¡ã€ã«ãããŠã³ããŒãããShoeStoreActions.loadShoesïŒourDataïŒã¡ãœãããåŒã³åºããŠããã€ããŒããDispatcherã«è»¢éããŸããããã«ããããµãã¹ã¯ã©ã€ããŒã«éä¿¡ãããŸãã ãããã£ãŠãShoeStoreã¯ãã®ã€ãã³ãã«ã€ããŠåŠç¿ããããã€ãã®éŽã®èµ·åã¡ãœãããåŒã³åºããŸãã
ã³ã³ãããŒã©ãŒãã¥ãŒ
ãã¥ãŒã¯ãå€æŽã€ãã³ãã«ãµãã¹ã¯ã©ã€ããããReactã³ã³ããŒãã³ãã§ããããªããžããªããã¢ããªã±ãŒã·ã§ã³ã®ç¶æ ãåãåããŸãã 次ã«ãããããã£ãä»ããŠãã®ããŒã¿ãåã³ã³ããŒãã³ãã«æž¡ããŸãã

ããã¯æ¬¡ã®ãããªãã®ã§ãã
/** @jsx React.DOM */ var React = require('react'); var ShoesStore = require('../stores/ShoeStore'); // function getAppState() { return { shoes: ShoeStore.getShoes() }; } // React- var ShoeStoreApp = React.createClass({ // getAppState, getInitialState: function() { return getAppState(); }, // componentDidMount: function() { ShoeStore.addChangeListener(this._onChange); }, // componentWillUnmount: function() { ShoesStore.removeChangeListener(this._onChange); }, render: function() { return ( <ShoeStore shoes={this.state.shoes} /> ); }, // "change" _onChange: function() { this.setState(getAppState()); } }); module.exports = ShoeStoreApp;
ã泚æ åäœïŒReactã®çŸåšã®ããŒãžã§ã³ã§ã¯ãã³ã³ããŒãã³ãã¯ãããã«ç°ãªãæ¹æ³ã§äœæãããŸãã
äžèšã®äŸã§ã¯ãaddChangeListenerã䜿çšããŠVaultã®æŽæ°ããµãã¹ã¯ã©ã€ããããchangeãã€ãã³ããåãåã£ããšãã«ç¶æ ãæŽæ°ããŸãã
ã¢ããªã±ãŒã·ã§ã³ã®ç¶æ ã¯ãªããžããªã«ä¿åãããããããªããžããªã€ã³ã¿ãŒãã§ãŒã¹ã䜿çšããŠãã®ããŒã¿ãååŸããã³ã³ããŒãã³ãã®ç¶æ ãæŽæ°ããŸãã
ãã¹ãŠããŸãšãã
Fluxã¢ãŒããã¯ãã£ã®åºæ¬çãªéšåããã¹ãŠç¢ºèªããã®ã§ããã®ã¢ãŒããã¯ãã£ãå®éã«ã©ã®ããã«æ©èœããããããããç解ã§ããŸãã èšäºã®æåããã®ããã»ã¹å³ãèŠããŠããŸããïŒ ã¹ããªãŒã ã®åéšåã®æ©èœãç解ããã®ã§ããããããã詳ããèŠãŠã¿ãŸãããã

ãããã«
ãã®èšäºããFacebookã®Fluxã¢ãŒããã¯ãã£ã®ç解ã«åœ¹ç«ã€ããšãé¡ã£ãŠããŸãã React.jsãå®éã«è©ŠããŠã¿ããŸã§ãReact.jsãã©ãã»ã©äŸ¿å©ãã¯çãããããŸããã§ããã
äžåºŠFluxã䜿çšãããšãFluxã䜿çšããã«Reactã§ã¢ããªã±ãŒã·ã§ã³ãèšè¿°ããããšã¯ãjQueryã䜿çšããã«DOMãæäœããããšã«äŒŒãŠãããšæããã§ãããã ã¯ããå¯èœã§ããããšã¬ã¬ã³ãã§æŽç¶ãšèŠããŸãã
Fluxã¢ãŒããã¯ãã£ã«æºæ ãããããReactãæ°ã«å ¥ããªãå Žåã¯ãRactive.jsãŸãã¯Flightãšçµã¿åãããããšãã§ããFluxãã¬ãŒã ã¯ãŒã¯ã§ããDeloreanãè©ŠããŠãã ããã ãã1ã€ã®æ³šç®ã«å€ããã©ã€ãã©ãªã¯Fluxxorã§ã ãããã¯ãFluxã¢ãŒããã¯ãã£ã«å¯ŸããŠãããã«ç°ãªãã¢ãããŒããæ¡çšããåäžã€ã³ã¹ã¿ã³ã¹ã®Fluxã³ã³ããŒãã³ãéã®ããç·å¯ãªãªã³ã¯ã䌎ããŸãã
Fluxãå®å šã«ç解ããã«ã¯ãè©ŠããŠã¿ãå¿ èŠãããã®ã§ãReactãã¥ãŒããªã¢ã«ã·ãªãŒãºã®æåŸã®4çªç®ã®ããŒãããèªã¿ãã ãããReact.jsãšFluxã¢ãŒããã¯ãã£ã䜿çšããŠç°¡åãªãªã³ã©ã€ã³ã¹ãã¢ãäœæããŸãã