點燈坊

失くすものさえない今が強くなるチャンスよ

使用 ap 將 Object 平行寫入 State

Sam Xiao's Avatar 2021-07-10

若想將 API 回傳 Object 的 Property 寫入多個 State,可使用 ap 平行寫入。

Version

Vue 3.0.11
Sanctuary 3.1.0
Fluture 14.0.0

tap

ap000

按下 Get Book,同時寫入 idtitle state。

<template lang='pug'>
button(@click='onClick') Get Book
div {{ id }} : {{ title }}
</template>

<script setup>
import { ref } from 'vue'
import { write } from 'vue3-fp'
import { tap } from 'ramda'
import S from 'sanctuary'
import { error } from 'wink-fp'
import { fork, mapRej } from 'fluture'
import getBook from '/src/api/getBook_'

let { prop, props, compose, unchecked: { pipe, map }} = S

let id = ref ('')
let title = ref ('')

let effect = pipe ([
  tap (compose (write (id)) (prop ('id'))),
  tap (compose (write (title)) (prop ('title')))
])

let onClick = pipe ([
  getBook (1),
  map (prop ('data')),
  mapRej (props (['response', 'data', 'error'])),
  fork (error) (effect)
])
</script>

26 行

let onClick = pipe ([
  getBook (1),
  map (prop ('data')),
  mapRej (props (['response', 'data', 'error'])),
  fork (error) (effect)
])

使用 pipe 組合 onClick

  • getBook (1):將 id 傳入 getBook 回傳 Future
  • map (prop ('data')):在 Resolved 內取得 data 回傳 Object
  • mapRej (props (['response', 'data', 'error'])):在 Rejected 內取得 response.date.error
  • fork (error) (effect):從 Future 內處理 Rejected 與 Resolved

21 行

let effect = pipe ([
  tap (compose (write (id)) (prop ('id'))),
  tap (compose (write (title)) (prop ('title')))
])

使用 pipe 組合 effect

  • tap (compose (write (id)) (prop ('id'))):先取得 id 再寫入 id state
  • tap (compose (write (title)) (prop ('title'))):先取得 title 再寫入 title state

ap

<template lang='pug'>
button(@click='onClick') Get Book
div {{ id }} : {{ title }}
</template>

<script setup>
import { ref } from 'vue'
import { write } from 'vue3-fp'
import S from 'sanctuary'
import { error } from 'wink-fp'
import { fork, mapRej } from 'fluture'
import getBook from '/src/api/getBook_'

let { prop, props, unchecked: { pipe, map, ap }} = S

let id = ref ('')
let title = ref ('')

let effect = ap ({
  id: write (id),
  title: write (title)
})

let onClick = pipe ([
  getBook (1),
  map (prop ('data')),
  mapRej (props (['response', 'data', 'error'])),
  fork (error) (effect)
])
</script>

25 行

let onClick = pipe ([
  getBook (1),
  map (props (['data'])),
  mapRej (props (['response', 'data', 'error'])),
  fork (error) (effect)
])

使用 pipe 組合 onClick

  • getBook (1):將 id 傳入 getBook 回傳 Future
  • map (prop ('data')):在 Resolved 內取得 data 回傳 Object
  • mapRej (props (['response', 'data', 'error'])):在 Rejected 內取得 response.date.error
  • fork (error) (effect):從 Future 內處理 Rejected 與 Resolved

20 行

let effect = ap ({ 
  id: write (id), 
  title: write (title) 
})

使用 ap 組合 effect

  • id: write (id):讀取 id property 並寫入 id state
  • title: write (title) :讀取 title property 並寫入 title state

Conclusion

  • Sanctuary 的 ap 支援 Object,因此剛好適合將 Object 平行寫入 State,且 ap 寫法也遠比 tap 精簡

Reference

Sanctuary, ap