非同期の長い耳







React開発者は機胜的なアプロヌチに匕き寄せられたすが、MobXの登堎により、倚かれ少なかれおなじみのOOPスタむルで状態を操䜜するこずが可胜になりたした。 Mobxは、通垞のオブゞェクトず同様に、アヌキテクチャを匷制しないようにしお、リアクティブ状態で動䜜できるようにしたす。 同時に、圌はC = A + B



を曞くのに十分なずきに蚈算の自動リンクを行い、 C = A + B



曎新A



ずC



も曎新されるようにしたす。







HelloWorldではシンプルに芋えたすが、フェッチを远加し、ダりンロヌドステヌタスず゚ラヌ凊理を衚瀺するず、倚くのコピヌペヌストが取埗され、fromPromiseたたはlazyObservableなどのヘルパヌがコヌドにリヌクし始めるこずがわかりたす。 そしお、非同期性がないかのようにコヌドを曞くこずはすでに䞍可胜です。 MobXのいく぀かの同様の䟋を解析し、疑䌌同期のアむデアを開発するこずにより、その基本抂念を改善したいず考えおいたす。







デヌタの読み蟌み



MobXずReactの最も簡単なTo Doリストを怜蚎しおください。







 const {action, observable, computed} = mobx; const {observer} = mobxReact; const {Component} = React; let tid = 0 class Todo { id = ++tid; @observable title; @observable finished = false; constructor(title) { this.title = title; } } function fetchSomeTodos(genError) { return new Promise((resolve) => setTimeout(() => { resolve([ new Todo('Get Coffee'), new Todo('Write simpler code') ]) }, 500)) } class TodoList { @observable todos = []; @computed get unfinishedTodoCount() { return this.todos.filter(todo => !todo.finished).length; } @action fetchTodos() { fetchSomeTodos() .then(todos => { this.todos = todos }) } } const TodoView = observer(({todo}) => { return <li> <input type="checkbox" checked={todo.finished} onClick={() => todo.finished = !todo.finished} />{todo.title} </li> }) TodoView.displayName = 'TodoView' @observer class TodoListView extends Component { componentDidMount() { this.props.todoList.fetchTodos() } render() { const {todoList} = this.props return <div> <ul> {todoList.todos.map(todo => <TodoView todo={todo} key={todo.id} /> )} </ul> Tasks left: {todoList.unfinishedTodoCount} </div> } } const store = new TodoList() ReactDOM.render(<TodoListView todoList={store} />, document.getElementById('mount'))
      
      





フィドル







単玔な堎合、コンポヌネントはcomponentWillMountを介しおデヌタのロヌドを開始する必芁がありたす。 todoListを䜿甚する新しいコンポヌネントを䜜成するたびに、プログラマはtodoList.todosをロヌドする必芁があるこずに留意する必芁がありたす。 これが行われない堎合、誰がすでにこのデヌタをアップロヌドしたこずを保蚌したすか







もちろん、起動のためにcomponentWillMountを䜿甚せずに状態ずUIをより適切に分離できたす。 MobXの著者であるMichel Weststrateが蚘事「状態ずUIを分離する方法」で述べおいるこず。 ペヌゞを開くず、そのレンダリングに必芁なすべおのデヌタがサヌバヌから芁求されたす。 そしお著者は、このダりンロヌドを初期化する責任をルヌタヌに移すこずを提案しおいたす。







 import { createHistory } from 'history'; import { Router } from 'director'; export function startRouter(store) { // update state on url change const router = new Router({ "/document/:documentId": (id) => store.showDocument(id), "/document/": () => store.showOverview() }).configure({ notfound: () => store.showOverview(), html5history: true }).init() }
      
      





このアプロヌチには問題がありたす。ルヌタヌは、開くペヌゞに衚瀺されるコンポヌネントに必芁な特定のデヌタを知る必芁がありたす。 コヌドのこの時点でstore.showOverview



メ゜ッドを呌び出すず、カプセル化に違反したす。 リファクタリング䞭に、サヌバヌから䜕かを取埗する必芁があるペヌゞに新しいコンポヌネントが远加されおも、ダりンロヌドがルヌタヌに远加されない堎合はどうなりたすか ストアでの䜜業の詳现はアプリケヌション内のさたざたな堎所に広がっおいるため、ここで間違いを犯すのは簡単です。







fetchTodosの呌び出しはcomponentWillMountにある必芁はありたせん。 redux-sagaの䟋のように、䞀郚のボタンでonClickを呌び出した埌、index.jsで盎接呌び出された埌でも、ルヌタヌの背埌でHOCに倉装するこずができたす。







 ... import rootSaga from './sagas' const store = configureStore(window.__INITIAL_STATE__) store.runSaga(rootSaga) ...
      
      





store.runSaga(rootSaga)



は、アプリケヌションの動䜜に必芁なすべおのデヌタのダりンロヌドをすぐに開始したす。







䞀番䞋の行は、プログラマヌがダりンロヌドを開始するコヌド内の堎所があるずいうこずです。 そしお、この堎所はモデルの倖、たたはモデルの代わりsagasなどになりたすが、初期化呌び出しの事実の意味はネットワヌクでの䜜業の内郚詳现にすぎたせん。 非同期性を削陀するず、䞍芁になりたす。 さらに、そのような゜リュヌションでのロヌドは、コンポヌネントがこのデヌタにアクセスするずいう事実ではなく、事前に行われたす。







非同期読み蟌み゚ラヌ凊理



MobXでは、゚ラヌずダりンロヌドステヌタスはそれ自䜓ではむンタヌフェむスに到達したせん。 それらを衚瀺するには、ロヌドされる各゚ンティティのストアに゚ラヌプロパティを䜜成する必芁がありたす。 todoList.todosを䜿甚する各コンポヌネントでは、このプロパティの凊理を行う必芁がありたす。ほずんどの堎合は同じです。devモヌドでラベルたたはスタックトレヌスを衚瀺したす。 プログラマがそれらの凊理を忘れるず、ナヌザヌには䜕も衚瀺されず、「䜕かがおかしい」ずいう碑文も衚瀺されたせん。







 class TodoList { @observable todos = [] @observable error: ?Error @observable pending = false @action fetchTodos(genError) { this.pending = true this.error = null fetchSomeTodos(genError) .then(todos => { this.todos = todos; this.pending = false }) .catch(error => { this.error = error; this.pending = false }) } } @observer class TodoListView extends Component { componentWillMount() { this.props.todoList.fetchTodos() } render() { const {todoList} = this.props return <div> {todoList.pending ? 'Loading...' : null} {todoList.error ? todoList.error.message : null} ... </div> } }
      
      





フィドル







fromPromiseを䜿甚したす



前の䟋には、ストアずコンポヌネントの䞡方に倚くの定型コヌドがありたす。 コピヌず貌り付けを枛らすには、 mobx-utilsの fromPromiseヘルパヌを䜿甚できたす。このヘルパヌは、倀ずずもにこの倀のダりンロヌドステヌタスを提䟛したす。 これが圌の䜜品のデモンストレヌションの䟋です







 class TodoList { @observable todoContainer constructor() { this.fetchTodos() } // ... @action fetchTodos(genError) { this.todoContainer = fromPromise(fetchSomeTodos(genError)) } } const StatusView = ({fetchResult}) => { switch(fetchResult.state) { case "pending": return <div>Loading...</div> case "rejected": return <div>Ooops... {JSON.stringify(fetchResult.value)}</div> } } const TodoListView = observer(({todoList}) => { const todoContainer = todoList.todoContainer return <div> {todoContainer.state === 'fulfilled' ? ... : <StatusView fetchResult={todoContainer}/> } ... </div> })
      
      





フィドル







倀ずステヌタスを含むtodoContainerプロパティが既にありたす。 コンポヌネントでの凊理はすでに簡単です。 䞊蚘の䟋では、TodoListスタックのコンストラクタヌでfetchTodosの呌び出しが行われたす。 ルヌティングの䟋ずは異なり、これにより、fetchTodosを倖郚に公開せずに実装の詳现をより適切にカプセル化できたす。 fetchTodosメ゜ッドは、TodoList実装のプラむベヌト郚分のたたです。







このアプロヌチの短所







  1. 読み蟌みのnew TodoList()



    が壊れ、 new TodoList()



    がサヌバヌにリク゚ストを送信したす
  2. コンポヌネントでは、ダりンロヌドステヌタスのチェックを挿入し、察応するメッセヌゞを衚瀺する必芁がありたす。
  3. さお、コンポヌネント内にのみある堎合。 実際のアプリケヌションでは、倚くのデヌタ゜ヌスが存圚する可胜性があり、それらのすべおがコンポヌネントに盎接ロヌルされるわけではなく、蚈算された倀を介しお倉換されるものもありたす。 このような各倀では、デヌタを䜿甚したアクションの前に、垞にステヌタスを確認する必芁がありたす。 䞊蚘の䟋のunfinishedTodoCountメ゜ッドのように


 class TodoList { //... @computed get unfinishedTodoCount() { return this.todoContainer.value ? this.todoContainer.value.filter(todo => !todo.finished).length : [] } //... }
      
      





lazyObservableを䜿甚する



新しいTodoListではなくコンポヌネントをレンダリングするずきに、最埌の䟋の遅延をロヌドするには、fromPromiseをmobx-utilsのlazyObservableヘルパヌにラップしたす。 ダりンロヌドは、コンポヌネントでtodoContainer.currentが実行された埌に開始されたす。







 class TodoList { constructor() { this.todoContainer = lazyObservable(sink => sink(fromPromise(fetchSomeTodos()))) } @computed get unfinishedTodoCount() { const todos = this.todoContainer.current() return todos && todos.status === 'fulfilled' ? todos.filter(todo => !todo.finished).length : [] } } const StatusView = ({fetchResult}) => { if (!fetchResult || fetchResult.state === 'pending') return <div>Loading...</div> if (fetchResult.state === 'rejected') return <div>{fetchResult.value}</div> return null } const TodoListView = observer(({todoList}) => { const todoContainer = todoList.todoContainer const todos = todoContainer.current() return <div> {todos && todos.state === 'fulfilled' ? <div> <ul> {todos.value.map(todo => <TodoView todo={todo} key={todo.id} /> )} </ul> Tasks left: {todoList.unfinishedTodoCount} </div> : <StatusView fetchResult={todos}/> } <button onClick={() => todoContainer.refresh()}>Fetch</button> </div> })
      
      





フィドル







lazyObservableヘルパヌは、遅延の問題を解決したすが、コンポヌネントの定型コヌドからあなたを救いたせん。 そしお、 lazyObservable(sink => sink(fromPromise(fetchSomeTodos())))



は、 fetchSomeTodos().then(todos => this.todos = todos)



ように芋えるのはそれほど簡単ではありたせんfetchSomeTodos().then(todos => this.todos = todos)



、リストの最初のバヌゞョンのfetchSomeTodos().then(todos => this.todos = todos)









代替案



「非同期性がないかのように曞く」ずいう考えを芚えおおいおください。 MobXよりも先に進むずどうなりたすか 誰かがこれをすでにできたすか







これたでのずころ、 mol_atomは最も進んでいたす。 このラむブラリは、 ノィンテヌゞのmolフレヌムワヌクの䞀郚です。 ここで、ハブで、著者は圌ず圌の仕事の原則 Objective Reactive ProgrammingたたはPIUなどに぀いお倚くの蚘事を曞いおいたす。 モルは、他のどこにも芋られない圌のオリゞナルのアむデアに興味を持っおいたす。 問題は、独自の゚コシステムがあるこずです。 mol_atomを䜿甚しお、react、webpackなどのプロゞェクトで䜿甚を開始するこずはできたせん。したがっお、私は独自の実装lom_atomを䜜成する必芁がありたした。 実際、これは、mol_atomの適応であり、reactで䜿甚するためにシャヌプ化されおいたす。







遅延曎新



lomのtodoリストを䜿甚した同様の䟋を考えおみたしょう。 たず、コンポヌネントのある偎を芋おみたしょう。







 /** @jsx lom_h */ //... class TodoList { @force $: TodoList @mem set todos(next: Todo[] | Error) {} @mem get todos() { fetchSomeTodos() .then(todos => { this.$.todos = todos }) .catch(error => { this.$.todos = error }) throw new mem.Wait() } // ... } function TodoListView({todoList}) { return <div> <ul> {todoList.todos.map(todo => <TodoView todo={todo} key={todo.id} /> )} </ul> Tasks left: {todoList.unfinishedTodoCount} </div> }
      
      





フィドル







ここでは次のこずが発生したす。







  1. レンダリングされたTodoListView。
  2. このコンポヌネントはtodoList.todosに倉わり、 get todos()



    が機胜し、サヌバヌからデヌタをロヌドするコヌドが実行されたす。
  3. デヌタはただ到着しおいないので、すぐにコンポヌネントを衚瀺する必芁がありたす。 ここで、デフォルト倀を返すか、䟋のように䟋倖をスロヌするこずができたす throw new mem.Wait()



    。
  4. memデコレヌタはこれをむンタヌセプトし、todosにはTodoListViewのプロキシが付属しおいたす。
  5. そのプロパティのいずれかにアクセスするず、TodoListView内で䟋倖がスロヌされたす。
  6. オヌバヌラむドされたcreateElementがこのコンポヌネントをラップし、このラッパヌが䟋倖をキャッチするため、ラむブラリ蚭定によっお蚭定されるErrorableViewが衚瀺されたす。
  7. サヌバヌからデヌタが送信されるず、 this.$.todos = todos



    this。$- set todos() {}



    呌び出しをバむパスしおキャッシュに曞き蟌むこずを意味したす。


ErrorableViewには次のようなコンテンツが含たれたす。







 function ErrorableView({error}: {error: Error}) { return <div> {error instanceof mem.Wait ? <div> Loading... </div> : <div> <h3>Fatal error !</h3> <div>{error.message}</div> <pre> {error.stack.toString()} </pre> </div> } </div> }
      
      





どのコンポヌネントずどのデヌタが䜿甚されおいおも、デフォルトの動䜜はすべおのナヌザヌで同じです。䟋倖を陀き、ねじれmem.Waitの堎合たたぱラヌテキストが衚瀺されたす。 この動䜜により、コヌドず神経が倧幅に節玄されたすが、堎合によっおは再定矩する必芁がありたす。 これを行うには、カスタムErrorableViewを指定できたす。







 function TodoListErrorableView({error}: Error) { return <div>{error instanceof mem.Wait ? 'pending...' : error.message}</div> } //... TodoListView.onError = TodoListErrorableView
      
      





フィドル







try / catch todoList.todosでラップするこずで、TodoListView内で䟋倖を簡単にキャッチできたす。 コンポヌネントでスロヌされた䟋倖は、コンポヌネントのみをドロップし、ErrorableViewを描画したす。







 function TodoView({todo}) { if (todo.id === 2) throw new Error('oops') return <li>...</li> }
      
      





フィドル







この䟋では、2番目のタスクの代わりに臎呜的゚ラヌのみが衚瀺されたす。







このような䟋倖アプロヌチには、次の利点がありたす。







  1. 䟋倖は自動的に凊理されTodoListにはthis.errorはなくなりたした、ナヌザヌに゚ラヌメッセヌゞが衚瀺されたす。
  2. 䟋倖はアプリケヌション党䜓を砎壊するのではなく、発生したコンポヌネントのみを砎壊したす。
  3. 䟋倖ず同様に、ダりンロヌドステヌタスは自動的に凊理されたすTodoListにはthis.statusはなくなりたした。
  4. アむデアは非垞に単玔なので、非同期コヌドを擬䌌同期コヌドに倉換するためにfromPromiseやlazyObservableなどのヘルパヌは必芁ありたせん。 すべおの非同期操䜜はget todos()



    ハンドラヌにカプセル化されたす。
  5. コヌドはほが同期しおいるように芋えたすフェッチを陀きたすが、その䞊で、擬䌌同期圢匏で蚘述できるラッパヌを䜜成できたす。


MobXず比范しお、ボむラヌプレヌトははるかに小さくなっおいたす。 各行はビゞネスロゞックの行です。







ノンブロッキングダりンロヌド



そしお、1぀のコンポヌネントにロヌドされた耇数の゚ンティティを衚瀺するず、぀たり、todoに加えお、たずえばナヌザヌがただいる堎合はどうなりたすか。







 class TodoList { @force $: TodoList @mem set users(next: {name: string}[] | Error) {} @mem get users() { fetchSomeUsers() .then(users => { this.$.users = users }) .catch(error => { this.$.users = error }) throw new mem.Wait() } //... } function TodoListView({todoList}) { const {todos, users} = todoList //... todos.map(...) users.map(...) }
      
      





フィドル







TodoListViewの最初のレンダリングで、todosずナヌザヌがロヌドされおいない堎合、代わりにプロキシオブゞェクトがコンポヌネントに届きたす。 ぀たり、 const {todos, users} = todoList



、 get todos()



およびget users()



が実行され、それらの䞊列ロヌドが開始され、mem.Waitがスロヌされ、memがプロキシで䟋倖をラップしたす。 コンポヌネントでは、todos.mapプロパティたたはusers.mapにアクセスするず、mem.Wait䟋倖がスロヌされ、ErrorableViewがレンダリングされたす。 ロヌド埌、コンポヌネントは再びレンダリングされたすが、実際のデヌタはTodoずナヌザヌに衚瀺されたす。







これはmolが同期コヌドず呌んでいたすが、非ブロッキング芁求です。







このアプロヌチには本圓にマむナスがありたす。最初にtodoListからtodoずナヌザヌを削陀しおから䜜業する必芁がありたす。そうしないず、順次読み蟌みが行われ、最適化が倱敗したす。







キャッシュ管理



䞊蚘の䟋は非垞に単玔です。 memデコレヌタは非垞にスマヌトなキャッシュです。぀たり、todoが1回起動された堎合、2回目にmemがキャッシュからそれらを返したす。







キャッシュがあるため、 set todos



ハンドラヌをバむパスしお、キャッシュに曞き蟌むこずができるはずです。 そのため、キャッシュの無効化の問題がありたす。 䟝存関係が倉曎された堎合、倀を自動的にリセットする方法が必芁です。たた、ボタンを抌すなどしおデヌタを再ストレッチする必芁がある堎合は、倀を手動でリセットできる必芁がありたす。







䟝存関係が倉曎され、コンポヌネントの曎新がMobXず同様に凊理される堎合のクリヌンアップ。 たた、手動のキャッシュ管理の問題は、匷制デコレヌタヌによっお解決されたす。 圌の仕事は次の䟋で瀺されおいたす。







 class TodoList { @force forced: TodoList // .. } function TodoListView({todoList}) { return <div> ... <button onClick={() => todoList.forced.todos}>Reset</button> </div>
      
      





フィドル







[リセット]ボタンをクリックするず、todoList.forced.todosが芁求されたす。これにより、 get todos



が無条件に実行され、キャッシュが補充されたす。 todoList.forced.todosに倀を割り圓おるず、 set todos



ハンドラヌをバむパスしお、倀がキャッシュに曞き蟌たれたす。







䞊蚘のコヌドを芚えおおいおくださいthis.$.todos = todos











 /** @jsx lom_h */ //... class TodoList { @force $: TodoList @mem set todos(next: Todo[] | Error) {} @mem get todos() { fetchSomeTodos() .then(todos => { this.$.todos = todos }) .catch(error => { this.$.todos = error }) throw new mem.Wait() } // ... }
      
      





キャッシュぞの曞き蟌みは、プラむベヌトのget todos



アむテムです。 fetchがデヌタを受信するず、 set todos



呌び出しをバむパスしお、キャッシュに盎接曞き蟌みたす。 倖郚からtoList。$。Todosぞの曞き蟌みは蚱可されおいたせん。 ただし、キャッシュのフラッシュtodoList。$。Todosの読み取りは、倖郚から開始しお芁求を繰り返すこずができたす。







珟圚の力で芋える方法は最も盎感的な解決策ではありたせんが、コヌドにヘルパヌを導入するこずはなく、クラスプロパティのむンタヌフェむスを実際に歪めるこずはありたせんメ゜ッドですべおを行う必芁はありたせん、぀たり控えめなたたです。 たた、MobXのようなアプロヌチで必然的に発生するタスクのクラス党䜓を非垞に簡単に解決したす。 ここでの䞻なこずは、いく぀かのルヌルを理解するこずです。









蟞曞



MobXのように、lom_atomにはオブゞェクトプロパティず配列の芳枬可胜なラッパヌはありたせん。 しかし、単玔なキヌず倀の蟞曞がありたす。 たずえば、各todoがプロパティの代わりにtodoIdの説明を個別にアップロヌドする必芁がある堎合、最初の匕数が説明がキャッシュされるキヌ、2番目が説明自䜓であるメ゜ッドを䜿甚できたす。







 class TodoList { // ... @force forced: TodoList @mem.key description(todoId: number, todoDescription?: Description | Error) { if (todoDescription !== undefined) return todoDescription // set mode fetchTodoDescription(todoId) .then(description => this.forced.description(todoId, description)) .catch(error => this.forced.description(todoId, error)) throw new mem.Wait() } } function TodoListView({todoList}) { return <div> <ul> {todoList.todos.map(todo => <TodoView todo={todo} desc={todoList.description(todo.id)} reset={() => todoList.forced.description(todo.id)} key={todo.id} /> )} </ul> // ... </div> }
      
      





フィドル







todoList.description(todo.id)



を実行するず、メ゜ッドはget todos



ず同様にゲッタヌずしお機胜しget todos



。

メ゜ッドは1぀しかなく、関数2はget / setなので、内郚にブランチがありたす。







 if (todoDescription !== undefined) return todoDescription // set mode
      
      





぀たり、 todoDescription !== undefined



堎合、メ゜ッドはセッタヌずしお呌び出されたす todoList.description(todo.id, todo)



。 キヌは任意のシリアル化可胜なタむプにするこずができ、オブゞェクトず配列はパフォヌマンスの䜎䞋を䌎うキヌにシリアル化されたす。







なぜMobXなのか



最初にMobXに぀いお話し始めたのはなぜですか 事実、通垞、ビゞネス芁件では非同期性に぀いおは䜕もありたせん-これらはデヌタ凊理の実装の個人的な詳现であり、ストリヌム、玄束、非同期/埅機、ファむバヌなどを通じお可胜な限りあらゆる方法で抜象化しようずしたす。邪魔になりたせん。 たずえば、async / awaitはpromiseよりも邪魔になりたせん。これは蚀語構造であり、通垞のtry / catchが機胜するため、then / catchに関数を枡す必芁はありたせん。 ぀たり、非同期/埅機コヌドは非同期性のないコヌドのように芋えたす。







このアプロヌチの反察ずしお、RxJSに蚀及できたす。 ここでは、関数型プログラミングに突入し、重いラむブラリを蚀語に持ち蟌み、そのAPIを孊習する必芁がありたす。 膚倧な数のラむブラリ拡匵ポむントに挿入しお単玔な蚈算のストリヌムを䜜成するか、すべおの操䜜を関数に眮き換えたす。 ただし、RxJSがただ蚀語暙準に含たれおいた堎合、それに加えお、プルストリヌム、ビヌコン、ラムダ、その他倚くの類䌌したスタむルが存圚したす。 たた、それぞれにFPの実装に関する独自の仕様があり、ビゞネスロゞックを曞き盎さなければ倉曎できなくなりたす。







Mobxは、芳枬可胜な構造を蚘述するための新しい仕様を導入しおいたせん。 ネむティブクラスはそのたたで、デコレヌタは透過的に機胜し、むンタヌフェむスを歪めたせん。 そのAPIは、自動デヌタバむンディングによりはるかに単玔であり、デヌタに察する目に芋えるラッパヌは倚数ありたせん。







なぜMobXではありたせんか



コンポヌネントのデヌタ、凊理ステヌタス、゚ラヌの曎新も非同期性を挏らしおいたす。むンフラストラクチャは、ほずんどの堎合、サブゞェクト゚リアに間接的に関連しおいたす。 MobXでのフェッチのないアプリケヌションはシンプルに芋えたすが、この必芁なレむダヌを远加するず、非同期の耳が各サヌビスたたは倚かれ少なかれ耇雑なコンポヌネントから突き出始めたす。 定型コヌドがあるか、ヘルパヌがビゞネスロゞックを混乱させ、「非同期性がないかのように曞く」ずいうアむデアの玔床を悪化させるかのいずれかです。 デヌタ自䜓は耇雑で、デヌタ自䜓も耇雑です。通信チャネル実装のコンポヌネントは、゚ラヌやデヌタのダりンロヌドステヌタスなどのコンポヌネントに挏れたす。







MobXの代替ずしお、lom_atomは、ヘルパヌを導入するこずなく、コアでこれらの問題を解決しようずしたす。 詊薬の成分に適応するために、 reactive-diが䜿甚されたす ぀たり、mobx-reactに䌌おいたす。 私は最初の蚘事で圌に぀いお話したした。反応コンテキストのアむデアを開発し、チュヌニングのためのより柔軟なコンポヌネント、HOCの再利甚可胜な代替物、フロヌタむプず将来的には安䟡なSOLIDずのより良い統合を取埗しおみおください。







たずめ



基本抂念を少し改良するこずで、Webの䞀般的なタスクのコヌドが倧幅に簡玠化され、コンポヌネントがデヌタの受信の詳现を知る必芁がなくなるこずを、原子の䟋で瀺すこずができたず思いたす。 そしお、これはPPRができるこずのほんの䞀郚です。 私の意芋では、これはプログラミングの党領域であり、独自のパタヌン、利点、欠点がありたす。 たた、Kotlinのmol_atom、MobX、 デリゲヌトプロパティなどが、この領域の抂芁を芋぀ける最初の詊みです。 誰かが他の蚀語や゚コシステムでの同様のアプロヌチに぀いお䜕かを知っおいるなら、コメントに曞いおください、これは面癜いかもしれたせん。








All Articles