
ãã·ã¢èªã話ãåå¿ã³ãã¥ããã£ã®ãã£ãããé»å ±ïŒ 
https://t.me/react_js ïŒã§èªããšãmobxã®è°è«ãäžå®ã®èŠåæ§ã§çŸããreduxãšã®æ¯èŒã§éæ³ãè€éãããå¯å€æ§ãã«ã€ããŠã®è°è«ãããã mobxãšã¯äœããã©ã®mobxã解決ããã®ãã«ã€ããŠã®å€§ããªèª€è§£ã ãããŠããã¹ãŠã®è°è«ã1ã€ã®æçš¿ã§åéã§ããããã«ããã®èšäºããå ±åãã§æžãããšã«ããŸããã ç¬èªã®ããŒãžã§ã³ã®mobxãå®è£
ããããšã«ãããmobxãå
éšããã©ã®ããã«æ©èœããããåæããreduxã®æ©èœãšæ¯èŒããŸãã
ãŸããmobxã¯ãç¶æ
管çã©ã€ãã©ãªãšããŠä»ã®ã©ã€ãã©ãªãšæ¯èŒãã@observableãã³ã¬ãŒã¿@observableããŒã¯ãããããããã£ã倿Ž@observableåŸãreactã®ã³ã³ããŒãã³ããåŒã³åºãããšãé€ããŠãç¶æ
ãæäœããããã®å©äŸ¿æ§ãã»ãšãã©æäŸããŸããã ãã¹ãŠã®@observableããã³@observerãã³ã¬ãŒã¿ãŒãåé€ããåäœäžã®ã¢ããªã±ãŒã·ã§ã³ãååŸããããšã§ã @observableãç°¡åã«ç Žæ£ã§ããŸããã³ã³ããŒãã³ãã«è¡šç€ºãããç¶æ
ããŒã¿ã倿Žãããã¹ãŠã®ã€ãã³ããã³ãã©ãŒã®æåŸã«update()ã1è¡è¿œå ããã ãã§ãã
 onCommentChange(e){ const {comment} = this.props; comment.text = e.target.value; update(); //   } 
ãããŠupdateïŒïŒé¢æ°ã¯åã«reactã¢ããªã±ãŒã·ã§ã³ã®ãåã¬ã³ãã©ãŒããåŒã³åºããreactã®ä»®æ³éåœã®ãããã§ãå®éã®æèã§ã¯diffã®å€æŽã®ã¿ãé©çšãããŸã
 function update(){ ReactDOM.render(<App>, document.getElementById('root'); } 
mobxã¯ãã³ãã©ãŒå
ã®update() 1è¡ãä¿åããã®ã§ãã¹ããŒããããŒãžã£ãŒå
šäœã§ãããšèšãã®ã¯ãããã¶ãå€ãããŸãã
察ç
§çã«ãreduxã§ã¯ãç¶æ
ãé©åã«æŽæ°ããã«å€æŽãªããžã§ã¯ãïŒã¢ã¯ã·ã§ã³ïŒãããã£ã¹ããããããå®å
šã«ç°ãªãå Žæã§åŠçããå ŽåïŒããããçŽç²ãªã¬ãã¥ãŒãµãŒé¢æ°ïŒã§ãã€ãã³ããœãŒã·ã³ã°ãã¿ãŒã³ãéããŠç¶æ
ã§äœæ¥ãæŽçã§ããŸããã€ãã³ããã¹ã«ãããã«ãŠã§ã¢ãã€ãã©ã€ã³ã§ãããã®ã¢ã¯ã·ã§ã³ãã€ã³ã¿ãŒã»ããããã¿ã€ã ãã©ãã«æ©èœãä»ããŠãããã°ã¢ããªã±ãŒã·ã§ã³ã簡玠åããããšã«ãããéåæã®äŸ¿å©ãªäœæ¥ã远å ã§ããŸãã
ã€ãŸããmobxã¯ç¶æ
ã®åŠçãåçŽåããã©ã€ãã©ãªã§ã¯ãããŸããããã®äž»ãªã¿ã¹ã¯ã¯äœã§ããïŒ ãã®äž»ãªã¿ã¹ã¯ã¯ãã³ã³ããŒãã³ãã®ãã€ã³ãããšã®æŽæ°ã§ããã€ãŸãã倿ŽãããããŒã¿ã«äŸåããã³ã³ããŒãã³ãã®ã¿ãæŽæ°ããŸãã
äžèšã®äŸã§ã¯ãã¢ããªã±ãŒã·ã§ã³ã®ããŒã¿ã倿ŽãããReactDOM.render(<App>, document.getElementById('root'))ã«ã update()颿°ã§ReactDOM.render(<App>, document.getElementById('root'))ãåŒã³åºããŠãã¢ããªã±ãŒã·ã§ã³å
šäœã®ãåã¬ã³ãã©ãŒãïŒä»®æ³æèæ¯èŒïŒãå®è¡ããŸããããã¯ããã©ãŒãã³ã¹ã«åœ±é¿ããå€§èŠæš¡ãªã¢ããªã±ãŒã·ã§ã³ã§ã¯ã€ã³ã¿ãŒãã§ãŒã¹ã®é床ãäœäžããããšã¯é¿ããããŸããã
çŸå®ã®éåœã¯é
ããšããã¹ããŒã¬ã³ãšãã¡ã¢ãªå
ã®ãªããžã§ã¯ãã®ããªãŒã®ã¿ãæ¯èŒããããä»®æ³éåœã§åå¿ããä»®æ³éåœãçã¿åºãããšããäºå®ã«ãããããããå®éã®éåœã§ã¯å€æŽãããéšåã®ã¿ãæŽæ°ããŸãããå®éã«ã¯ã¢ããªã±ãŒã·ã§ã³ã®ããŒã¿ãæŽæ°ããããã³ã«ãããåŒã³åºãããšã¯ã§ããŸããé
ããããã¢ããªã±ãŒã·ã§ã³å
šäœã®ä»®æ³ã®éåœãæ¯èŒããŸãã
ãããŠãåé¡ã®è§£æ±ºçã¯ä»®æ³éåœã«äŸåãããã³ã³ããŒãã³ããæåã§æŽæ°ããåºåããããŒã¿ã倿Žãããã³ã³ããŒãã³ãã®ã¿ã®
this.forceUpdate()åŒã³åºããŸãã
ãããŠããã®åé¡ã¯ããŸãã«mobxã©ã€ãã©ãªãšreduxã©ã€ãã©ãªã®äžéšã解決ãããã®ã§ãã
ããããããã2ã€ã®ã©ã€ãã©ãªãèæ
®ããã«ãã³ã³ããŒãã³ããåå¥ã«æŽæ°ããåé¡ã解決ããŠã¿ãŸãããã
ããã§ã¯ã2ã€ã®ã¢ãããŒããèãåºãããšãã§ããŸããã©ã¡ãããå·ãšã®é£æºæ¹æ³ã«å¶éã課ããŸãã
æåã®ã¢ãããŒãã¯äžå€æ§ãšãã€ããªæ€çŽ¢ã䜿çšããããšã§ã-åç¶æ
ã®æŽæ°ããã¹ãŠã®èŠªãªããžã§ã¯ãã«å¯ŸããŠå€æŽãããæ°ããããŒã¿ãªããžã§ã¯ããè¿ãå ŽåïŒç¶æ
ã«éå±€æ§é ãããå ŽåïŒããªã³ã¯ãåãšæ°ãããšæ¯èŒããããšã§ã³ã³ããŒãã³ãã®ã»ãŒãã€ã³ãããšã®æŽæ°ãéæã§ããŸãããŒã¿ã倿ŽãããŠããªãã³ã³ããŒãã³ãïŒnewSubtree === oldSubtreeïŒã®ãã¹ãŠã®ãµãããªãŒãã¹ããŒãã¹ããããããã®çµæãå¿
èŠãªcomã®ã¬ã³ãã©ãŒãåŒã³åºããŠã¢ããªã±ãŒã·ã§ã³ãæŽæ°ããŸãã æ§æèŠçŽ ã®æ°ã§ãã - onenta nåã®ããŒã¿ã®ã¿OïŒãã°ïŒNïŒïŒã®æåãšæ¯èŒã
ãããã£ãŠãããšãã°ã 
ChangeDetectionStrategy.OnPushèšå®ãããšè§åºŠã¯æ©èœããŸãã ããããäžããäžã«äžããšããæ±ºå®ã«ã¯ãããã€ãã®æ¬ ç¹ããããŸãã ãŸããOïŒlogïŒnïŒïŒã®å¹çã«ãããããããããã³ã³ããŒãã³ããä»ã®ã³ã³ããŒãã³ãã®ãªã¹ãã衚瀺ããå Žåãã³ã³ããŒãã³ãã®é
åå
šäœã調ã¹ãŠå°éå
·ãæ¯èŒãããªã¹ãã®åã³ã³ããŒãã³ããå¥ã®ãªã¹ããã¬ã³ããªã³ã°ããå Žåããã®åŸãæ¯èŒã®æ°ãããã«å¢å ãââãŸãã 第äºã«-ã³ã³ããŒãã³ãã¯ç¬èªã®ããããã®ã¿ã«äŸåããå¿
èŠããããããããã¯å€ãã®å Žåãäžéã³ã³ããŒãã³ããä»ããŠã¹ããŒããå¿
èŠããããŸãã
reduxã©ã€ãã©ãªãŒãäžå€ã®ã¢ãããŒãã䜿çšããŸããããããã«å€æŽããã ãã§ãå°éå
·ã®ã¿ã«äŸåãããšããæ¬ ç¹ã解決ããŸãã reduxã¯ãå°éå
·ã®æ¯èŒã«å ããŠãç¶æ
ã®ç°ãªãéšåãžã®äŸåã瀺ã
mapStateToProps()颿°ïŒ 
connectãã³ã¬ãŒã¿ãŒïŒã«ãã£ãŠè¿ããã远å ããŒã¿ãæ¯èŒãããããã¯è¿œå ã®å°éå
·ã«ãªããŸãã ãã ãããã®ãããæ¥ç¶ã®ãã¹ãŠã®ã³ã³ããŒãã³ãããã§ãã¯ããå¿
èŠããããŸãã ãã ããããã§ãã¢ããªã±ãŒã·ã§ã³å
šäœã®æŽæ°ïŒ 
ReactDOM.render(<App>, rootEl); ïŒãããé«éã§ãã
ããããå
ç«çã¢ãããŒãã«ã¯ãåœå®¶ãšã®ååã«å¶éã課ãããã€ãã®éå€§ãªæ¬ ç¹ããããŸãã
æåã®æ¬ ç¹ã¯ãã¢ããªã±ãŒã·ã§ã³å
ã®ããŒã¿ãªããžã§ã¯ãã®ããããã£ãååŸããŠæŽæ°ããããšãã§ããªãããšã§ãã ç¶æ
å
šäœã®æ°ããäžå€ãªããžã§ã¯ããæ¯åè¿ãå¿
èŠããããããæ°ãããªããžã§ã¯ããè¿ãããã¹ãŠã®èŠªãªããžã§ã¯ããšé
åãåäœæããå¿
èŠããããŸãã ããšãã°ãç¶æ
ãªããžã§ã¯ãã«ãããžã§ã¯ãã®é
åãæ ŒçŽãããŠããå Žåãåãããžã§ã¯ãã«ã¯ã¿ã¹ã¯ã®é
åãæ ŒçŽãããåã¿ã¹ã¯ã«ã¯ã³ã¡ã³ãã®é
åãæ ŒçŽãããŸãã
 let AppState = { projects: [ {..}, {...}, {name: 'project3', tasts: [ {...}, {...}, {name: 'task3', comments: [ {...}, {...}, {text: 'comment3' } ]} ]} ] } 
ã³ã¡ã³ããªããžã§ã¯ãã®ããã¹ããæŽæ°ããããã«ã comment.text = 'new text'å®è¡ããããšã¯ã§ããŸãã-æåã«ã³ã¡ã³ããªããžã§ã¯ããåäœæããå¿
èŠããããŸãïŒ comment = {...comment, text: 'updated text'} ïŒã次ã«ããå¿
èŠããããŸãã¿ã¹ã¯ãªããžã§ã¯ããåäœæããããããä»ã®ã³ã¡ã³ããžã®ãªã³ã¯ãã³ããŒãïŒ task = {...task, tasks: [...task.comments]} ïŒããããžã§ã¯ããªããžã§ã¯ããåäœæããããã«ä»ã®ã¿ã¹ã¯ãžã®ãªã³ã¯ãã³ããŒããŸãïŒ project = {...project, tasks: [...project.tasks]} ïŒãããŠæåŸã«æ¢ã«ç¶æ
ãªããžã§ã¯ããåäœæããä»ã®ãããžã§ã¯ããžã®ãªã³ã¯ãã³ããŒããŸãïŒ AppStat = {...AppState, projects: [...AppState.projects]} ïŒ ã
2çªç®ã®æ¬ ç¹ã¯ãããç¶æ
ã§çžäºã«åç
§ãããªããžã§ã¯ããä¿åã§ããªãããšã§ãã ã³ã³ããŒãã³ããã³ãã©ãŒã®ã©ããã§ã¿ã¹ã¯ãé
眮ãããŠãããããžã§ã¯ããååŸããå¿
èŠãããå Žåããªããžã§ã¯ããäœæãããšãã«èŠªãããžã§ã¯ãtask.project = projectãžã®ãªã³ã¯ãåçŽã«å²ãåœãŠãããšã¯ã§ããŸãããäžå€ã®ã¢ãããŒãã®å¿
èŠæ§ã¯ã¿ã¹ã¯ã ãã§ãªãããããžã§ã¯ãã®ãã®ä»ã®ãã¹ãŠã®ã¿ã¹ã¯ãæŽæ°ããå¿
èŠããããšããäºå®ã«ã€ãªãããŸã-ãããžã§ã¯ããªããžã§ã¯ããžã®ãªã³ã¯ã倿ŽãããŸãããã€ãŸããæ°ãããªã³ã¯ãå²ãåœãŠãããšã§ãã¹ãŠã®ã¿ã¹ã¯ãæŽæ°ããå¿
èŠããããŸãã ãªããžã§ã¯ããã¿ã¹ã¯ãã³ã¡ã³ããä¿åãããŠããå Žåãšãæã
ã¯ã圌ããåé¡ã®ãªããžã§ã¯ããžã®åç
§ãæ ŒçŽããããããã³ã¡ã³ãã®ãã¹ãŠãåäœæããããã«å¿
èŠãªããšæã
ã¯ã«æ¥ãã®ã§ãååž°çã«å
šäœã®ç¶æ
ãåäœæãããããã²ã©ãé
ããªããŸãã
ãã®çµæãç®çã®ãªããžã§ã¯ãã転éãããã³ã«é«æ¬¡ã³ã³ããŒãã³ãã®å°éå
·ã倿Žãããããªããžã§ã¯ããåç
§ãã代ããã«task.project = '12345';ä¿åããtask.project = '12345'; ãããŠãèå¥åã«ãã£ãŠãããžã§ã¯ãã®ããã·ã¥ãä¿åããã³ç¶æããå ŽæProjectHash['12345'] = project;
äžå€æ§ã䌎ããœãªã¥ãŒã·ã§ã³ã«ã¯å€ãã®æ¬ ç¹ããããããç¹ããŒã¹ã®ã³ã³ããŒãã³ãæŽæ°ã®åé¡ãå¥ã®æ¹æ³ã§è§£æ±ºã§ãããã©ãããèããŠã¿ãŸãããã ã¢ããªã±ãŒã·ã§ã³ã®ããŒã¿ã倿Žããå Žåããã®ããŒã¿ã«äŸåããã³ã³ããŒãã³ãã®ã¿ãåã¬ã³ããªã³ã°ããå¿
èŠããããŸãã äŸåãšã¯ã©ãããæå³ã§ããïŒ ããšãã°ãã³ã¡ã³ãããã¹ãã衚瀺ããç°¡åãªã³ã¡ã³ãã³ã³ããŒãã³ãããããŸã
 class Comment extends React.Component { render(){ const {comment} = this.props; return <div>{comment.text}</div> } } 
ãã®ã³ã³ããŒãã³ãã¯comment.textäŸåããŠããã comment.textã倿Žããããã³ã«æŽæ°ããå¿
èŠããããŸãã ãã ããã³ã³ããŒãã³ãã«<div>{comment.parent.text}</div>ã衚瀺ãããå Žåã§ãã .textã ãã§ãªã.parentã.parentãã³ã«ã³ã³ããŒãã³ããæŽæ°ããå¿
èŠããã.parent ã å
ç«ã¢ãããŒããé©çšããã«ãã®åé¡ã解決ã§ããŸãããjavascriptã®getterããã³setterã®æ©èœã䜿çšããŸããããã¯ããã€ã³ãæŽæ°uiã®åé¡ã解決ããããã®2çªç®ã®ã¢ãããŒãã§ãã
ã²ãã¿ãŒãšã»ãã¿ãŒã¯ãããããã£ãæŽæ°ãããããããã£å€ãååŸããããããã³ãã©ãŒãé
眮ãããããªãå€ãjavascriptæ©èœã§ãã
 Object.defineProperty(comment, 'text', { get(){ console.log('>text getter'); return this._text; }, set(val){ console.log('>text setter'); this._text = val; } }) comment.text; //    >text getter comment.text = 'new text' //    >text setter 
ãã®ãããæ°ããå€ãå²ãåœãŠããããã³ã«å®è¡ããã颿°ãã»ãã¿ãŒã«é
眮ãããã®ããããã£ã«äŸåããã³ã³ããŒãã³ãã®ãªã¹ãã®ã¬ã³ãã©ãŒãåŒã³åºããŸãã ã©ã®ã³ã³ããŒãã³ããã©ã®ããããã£ã«äŸåããŠãããã調ã¹ãã«ã¯ãã³ã³ããŒãã³ãã®render()颿°ã®éå§æã«çŸåšã®ã³ã³ããŒãã³ããã°ããŒãã«å€æ°ã«å²ãåœãŠãå¿
èŠããããŸãããªããžã§ã¯ãã®ããããã£ã®getterãåŒã³åºããšãã¯ãã°ããŒãã«å€æ°ã«ãããã®ããããã£ã®äŸåé¢ä¿ãªã¹ãã«çŸåšã®ã³ã³ããŒãã³ãã远å ããå¿
èŠããããŸã ãŸããã³ã³ããŒãã³ãã¯ããªãŒç¶ã«ãã¬ã³ããªã³ã°ãã§ãããããåã®ã³ã³ããŒãã³ãããã®ã°ããŒãã«å€æ°ã«æ»ãããšãå¿ããªãã§ãã ããã
 let CurrentComponent; class Comment extends React.Component { render(){ const prevComponent = CurrentComponent; CurrentComponent = this; const {comment} = this.props; var result = <div>{comment.text}</div> CurrentComponent = prevComponent; return result } } comment._components = []; Object.defineProperty(comment, 'text', { get(){ this._components.push(CurrentComponent); return this._text }, set(val){ this._text = val; this._components.forEach(component => component.setState({})) } }) 
ç§ã¯ããªããã¢ã€ãã¢ãåŸããšæããŸãã ãã®ã¢ãããŒãã§ã¯ãåããããã£ã¯ãã®äŸåã³ã³ããŒãã³ãã®é
åãæ ŒçŽããããããã£ã倿ŽããããšããããæŽæ°ãããŸãã
ããã§ãäŸåã³ã³ããŒãã³ãã®é
åã®ã¹ãã¬ãŒãžãããŒã¿ãšæ··åãããã³ãŒãã簡玠åããããã«ããã®ãããªããããã£ã®ããžãã¯ãCellã¯ã©ã¹ã«åãåºããŸããããã¯ã顿šãããããããã«ãExcelã®ã»ã«ã®åçã«éåžžã«äŒŒãŠããŸã-ä»ã®ã»ã«ãçŸåšã®åŒã«äŸåããŠããå Žåã»ã«ãå€ã倿Žãããšããã¹ãŠã®äŸåã»ã«ãæŽæ°ãããŸãã
 let CurrentObserver = null; class Cell { constructor(val){ this.value = val; this.reactions = new Set(); //        es6  } get(){ if(CurrentObserver){ this.reactions.add(CurrentObserver); } return this.value; } set(val){ this.value = val; for(const reaction of this.reactions){ reaction.run(); } } unsibscribe(reaction){ this.reactions.delete(reaction); } } 
ãã ããåŒãæã€ã»ã«ã®åœ¹å²ã¯ã Cellã¯ã©ã¹ããç¶æ¿ããComputedCellã¯ã©ã¹ã«ãã£ãŠæããããŸãïŒä»ã®ã»ã«ã¯ãã®ã»ã«ã«äŸåããå¯èœæ§ãããããïŒã ComputedCellã¯ã©ã¹ã¯ãã³ã³ã¹ãã©ã¯ã¿ãŒã§åèšç®ã®ããã®é¢æ°ïŒåŒïŒãšãå¯äœçšïŒ .forceUpdate()ã³ã³ããŒãã³ãã®åŒã³åºããªã©ïŒãå®è¡ããããã®ãªãã·ã§ã³ã®é¢æ°ã.forceUpdate()ãŸã
 class ComputedCell extends Cell { constructor(computedFn, reactionFn, ){ super(undefined); this.computedFn = computedFn; this.reactionFn = reactionFn; } run(){ const prevObserver = CurrentObserver; CurrentObserver = this; const newValue = this.computedFn(); if(newValue !== this.value){ this.value = newValue; CurrentObserver = null; this.reactionFn(); this.reactions.forEach(r=>r.run()); } CurrentObserver = prevObserver; } } 
ãããŠãã²ãã¿ãŒãšã»ãã¿ãŒãæ¯åå®è¡ããªãããã«ãtypescriptãŸãã¯babelã®ãã³ã¬ãŒã¿ãŒã䜿çšããŸãã ã¯ããããã¯ã¯ã©ã¹ã䜿çšãããªãã©ã«const newComment = {text: 'comment1'}ãªãconst comment = new Comment('comment1')ãä»ããŠãªããžã§ã¯ããäœæããå¿
èŠæ§ã«å¶éã課ããŸãããã²ãã¿ãŒãšã»ãã¿ãŒãæåã§èšå®ãã代ããã«ãããããã£ã䟿å©ã«ããŒã¯ã§ããŸã@observableéåžžã®ããããã£ãšããŠãã@observableåŒãç¶ã䜿çšããæ¹æ³ã
 class Comment { @observable text; constructor(text){ this.text = text; } } function observable(target, key, descriptor){ descriptor.get = function(){ if(!this.__observables) this.__observables = {}; const observable = this.__observables[key]; if (!observable) this.__observables[key] = new Observable() return observable.get(); } descriptor.set = function(val){ if (!this.__observables) this.__observables = {}; const observable = this.__observables[key]; if (!observable) this.__observables[key] = new Observable() observable.set(val); } return descriptor } 
ãŸããã³ã³ããŒãã³ãå
ã®ComputedCellã¯ã©ã¹ãçŽæ¥æäœããªãããã«ããã®ã³ãŒãã@observerãã³ã¬ãŒã¿ãŒã«é
眮ããŸããããã¯ã render()ã¡ãœãããã©ããããæåã®åŒã³åºãã§èšç®ã»ã«ãäœæãã render()ã¡ãœãããåŒããã³é¢æ°ãšããŠæž¡ããŸãthis.forceUpdate()ã¯this.forceUpdate()åŒã³åºãthis.forceUpdate()å®éã«ã¯ã componentWillUnmount()ã¡ãœããã«ãµãã¹ã¯this.forceUpdate()è§£é€ã远å ãããªã¢ã¯ã·ã§ã³ã®ã³ã³ããŒãã³ãã®æ£ããã©ããã³ã°ã®ç¬éã远å ããå¿
èŠããããŸãããããã§ã¯çè§£ã容æã«ããããã«ãã®ãªãã·ã§ã³ãæ®ããŸãïŒ
 function observer(Component) { const oldRender = Component.prototype.render; Component.prototype.render = function(){ if (!this._reaction) this._reaction = new ComputedCell(oldRender.bind(this), ()=>this.forceUpdate()); return this._reaction.get(); } } 
ãšããŠäœ¿çšããŸã
 @observer class Comment extends React.Component { render(){ const {comment} = this.props; return <div>{comment.text}</div> } } 
ãã¢ãžã®ãªã³ã¯
ãã¹ãŠã®ã³ãŒãã¢ã»ã³ã㪠import React from 'react'; import { render } from 'react-dom'; let CurrentObserver; class Cell { constructor(val) { this.value = val; this.reactions = new Set(); } get() { if (CurrentObserver) { this.reactions.add(CurrentObserver); } return this.value; } set(val) { this.value = val; for (const reaction of this.reactions) { reaction.run(); } } unsubscribe(reaction) { this.reactions.delete(reaction); } } class ComputedCell extends Cell { constructor(computedFn, reactionFn) { super(); this.computedFn = computedFn; this.reactionFn = reactionFn; this.value = this.track(); } track(){ const prevObserver = CurrentObserver; CurrentObserver = this; const newValue = this.computedFn(); CurrentObserver = prevObserver; return newValue; } run() { const newValue = this.track(); if (newValue !== this.value) { this.value = newValue; CurrentObserver = null; this.reactionFn(); } } } function observable(target, key) { return { get() { if (!this.__observables) this.__observables = {}; let observable = this.__observables[key]; if (!observable) observable = this.__observables[key] = new Cell(); return observable.get(); }, set(val) { if (!this.__observables) this.__observables = {}; let observable = this.__observables[key]; if (!observable) observable = this.__observables[key] = new Cell(); observable.set(val); } } } function observer(Component) { const oldRender = Component.prototype.render; Component.prototype.render = function(){ if (!this._reaction) this._reaction = new ComputedCell(oldRender.bind(this), ()=>this.forceUpdate()); return this._reaction.get(); } } class Timer { @observable count; constructor(text) { this.count = 0; } } const AppState = new Timer(); @observer class App extends React.Component { onClick=()=>{ this.props.timer.count++ } render(){ console.log('render'); const {timer} = this.props; return ( <div> <div>{timer.count}</div> <button onClick={this.onClick}>click</button> </div> ) } } render(<App timer={AppState}/>, document.getElementById('root')); 
 ãã®äŸã§ã¯ã1ã€ã®æ¬ ç¹ããããŸããã³ã³ããŒãã³ãã®äŸåé¢ä¿ã倿Žãããå¯èœæ§ãããå Žåã¯ã©ãã§ããããã æ¬¡ã®ã³ã³ããŒãã³ããã芧ãã ãã
 class User extends React.Component { render(){ const {user} = this.props; return <div>{user.showFirstName ? user.firstName : user.lastName}</div> } } 
ã³ã³ããŒãã³ãã¯user.showFirstNameããããã£ã«äŸåããããã«å€ã«å¿ããŠã user.firstNameãŸãã¯user.lastNameããããã«äŸåã§ããŸããã€ãŸãã user.showFirstName == trueå Žåã user.showFirstName == true倿Žã«åå¿ããã¹ãã§ã¯ãããŸããã user.showFirstName falseã«å€æŽããããããããããã£user.firstNameå Žåãåå¿ïŒããã³ã³ã³ããŒãã³ãã¬ã³ãã©ãŒãå®è¡ïŒããªãã§user.firstName ã
ãã®ç¹ã¯ãäŸåé¢ä¿ãªã¹ãthis.dependencies = new Set()ãã»ã«ã¯ã©ã¹ã«è¿œå ãã run()颿°ã®å°ããªããžãã¯ã远å ããããšã§ç°¡åã«è§£æ±ºã§ããŸãããã®ãããåå¿ã®renderïŒïŒãåŒã³åºããåŸã以åã®äŸåé¢ä¿ã®ãªã¹ããæ°ãããã®ãšæ¯èŒããç¡é¢ä¿ãªäŸåé¢ä¿ãããµãã¹ã¯ã©ã€ããè§£é€ããŸãã
 class Cell { constructor(){ ... this.dependencies = new Set(); } get() { if (CurrentObserver) { this.reactions.add(CurrentObserver); CurrentObserver.dependencies.add(this); } return this.value; } } class ComputedCell { track(){ const prevObserver = CurrentObserver; CurrentObserver = this; const oldDependencies = this.dependencies;  
2çªç®ã®ãã€ã³ãã¯ããªããžã§ã¯ãã®å€ãã®ããããã£ãããã«å€æŽããå Žåã§ããïŒ äŸåã³ã³ããŒãã³ãã¯åæçã«æŽæ°ãããããã2ã€ã®è¿œå ã³ã³ããŒãã³ãæŽæ°ãååŸãããŸã
 comment.text = 'edited text'; //    comment.editedCount+=1; //    
äžèŠãªæŽæ°ãé¿ããããã«ããã®é¢æ°ã®å
é ã§ã°ããŒãã«ãã©ã°ãèšå®ã§ããŸãã @observerãã³ã¬ãŒã¿ãŒã¯ããã«this.forceUpdate()åŒã³åºããããã®ãã©ã°ãåé€ãããšãã«ã®ã¿åŒã³åºããŸãã ãããŠç°¡åã«ããããã«ããã®ããžãã¯ãactionãã³ã¬ãŒã¿ã«é
眮ãããã©ã°ã®ä»£ããã«ãã³ã¬ãŒã¿ãä»ã®ãã³ã¬ãŒã¿å
ã§åŒã³åºãããšãã§ãããããã«ãŠã³ã¿ã墿žããŸãã
 updatedComment = action(()=>{ comment.text = 'edited text'; comment.editedCount+=1; }) let TransactionCount = 0; let PendingComponents = new Set(); function observer(Component) { const oldRender = Component.prototype.render; Component.prototype.render = function(){ if (!this._reaction) this._reaction = new ComputedCell(oldRender.bind(this), ()=>{ TransactionCount ?PendingComponents.add(this) : this.forceUpdate() }); return this._reaction.get(); } } function action(fn){ TransactionCount++ const result = fn(); TransactionCount-- if(TransactionCount == 0){ for(const component of PendingComponents){ component.forceUpdate(); } } return result; } 
ãã®çµæãéåžžã«å€ãããªãã¶ãŒããŒããã¿ãŒã³ã䜿çšãããã®ã¢ãããŒãïŒãªãã¶ãŒããã«RxJSãšæ··åããªãã§ãã ããïŒã¯ãã€ãã¥ããã£ã¢ãããŒãããããã€ã³ãæŽæ°ã³ã³ããŒãã³ãã®ã¿ã¹ã¯ã«ããé©ããŠããŸãã
欠ç¹ã®ãã¡ããªãã©ã«ã§ã¯ãªãã¯ã©ã¹ãä»ããŠãªããžã§ã¯ããäœæããå¿
èŠãããããšã«æ°ä»ãããšãã§ããŸããã€ãŸãããµãŒããŒããäžéšã®ããŒã¿ã@observableãŠã³ã³ããŒãã³ãã«æž¡ãããšã¯ã§ããŸãããã¯ã©ã¹ãªããžã§ã¯ãã@observableãã³ã¬ãŒã¿ã§ã©ããããŠè¿œå ã®ããŒã¿åŠçãå®è¡ããå¿
èŠããããŸãã
欠ç¹ã«ã¯ããªããžã§ã¯ãã«æ°ããããããã£ããªã³ã¶ãã©ã€ã§è¿œå ã§ããªãããšïŒjsããã©ãŒãã³ã¹ã®èгç¹ããæ¢ã«ã¢ã³ããã¿ãŒã³ãšèŠãªãããŠããŸãïŒãããŒã¿ãã²ãã¿ãŒã®èåŸã«é ãããå€ã®ä»£ããã«3ã€ã®ãããã衚瀺ããããããã¯ãã devtoolsã®ã³ãŒããããã°ã®äžäŸ¿ããå«ãŸããŸããã®ããããã£ãã¯ãªãã¯ããå€ãããã³å€æŽãã¹ãããã¹ã«ãŒããããããããã£ãååŸããããšãããšãã©ã€ãã©ãªå
ã®ã»ãã¿ãŒãŸãã¯ã²ãã¿ãŒã«æ·±ãå
¥ããŸãã
ããããå©ç¹ã¯æ¬ ç¹ãã¯ããã«è¶
ããŠããŸãã ãŸããäžå€ã®ã¢ãããŒããšã¯ç°ãªããæŽæ°ã®å¿
èŠãªã³ã³ããŒãã³ãã®ãªã¹ããããã«ããããããäœæ¥ã®é床ã¯ã³ã³ããŒãã³ãã®æ°ã«äŸåããŸãã-ã€ãŸããoïŒlogïŒnïŒïŒãŸãã¯oïŒnïŒã®ä»£ããã«oïŒ1ïŒã®è€éãããããŸã
Den Abramovãããã«éèŠãªããšã«ãnãªããžã§ã¯ãã¯
mapStateToProps颿°ã§ã¯äœæãããŸããã æ¬¡ã«ãäžéšã®ããŒã¿ãæŽæ°ããå¿
èŠãããå Žåã 
comment.text = 'new text'ãšèšè¿°ããã ãã§ã芪ã®ç¶æ
ãªããžã§ã¯ããæŽæ°ããããã«å€ãã®äœæ¥ãè¡ãå¿
èŠã¯ãããŸãããéèŠãªããšã¯ãã¬ããŒãžã³ã¬ã¯ã¿ãŒã«è² è·ãããããªãããšã§ãããªããžã§ã¯ãã®æ°žç¶çãªã¬ã¯ãªãšãŒã·ã§ã³ã æãéèŠãªããš-çžäºã«åç
§ãããªããžã§ã¯ãã䜿çšããŠç¶æ
ãã¢ãã«åã§ãããªããžã§ã¯ãã®ä»£ããã«èå¥åãä¿åããããšãªãç¶æ
ãæäœã§ãã 
AppState.folders[AppState.projects[AppState.tasks[comment.taskId].projectId].folderId].nameã ãã§
AppState.folders[AppState.projects[AppState.tasks[comment.taskId].projectId].folderId].nameã¯ãªãã¯ãã代ããã«
ãããã«
â â "" mobx. mobx @computed ( ) mobx- react-.