【问题标题】:Elegant way to inject custom hook into evolve function将自定义钩子注入进化函数的优雅方式
【发布时间】:2020-01-28 23:47:04
【问题描述】:

我和我的团队每天都在强烈地结合 FP 和 react-hooks 模式,尽管有时我们很难将钩子与纯函数一起管理。最近,我们遇到了很多情况,其中钩子“回调”必须位于 compose 或另一个转换器内部的某个位置 - 在这种情况下,它是 evolve 函数,例如:

const getDefinedActions = R.filter(
      R.both(isActionDefined, R.ifElse(hasAfterConfirm, isAfterConfirmDefined, R.T))
    )
    
const translateTitles = R.map(
  R.evolve({
    title: title => useTranslate()(title)
  })
)

export const useActions = R.compose(
  translateTitles,
  getDefinedActions
)

在上面的例子中,我们想根据一些谓词+添加翻译来过滤掉动作,这需要使用useTranslate钩子。不幸的是,我们不能只写 useTranslate() 那里,因为钩子必须在 React 组件安装后初始化。到目前为止在这些情况下做了什么:

  • “即时”创建钩子函数,并将其传递给另一个 ramda 函数。例如{ const translate = useTranslate(); return R.compose(..., translate, ...) } - 我们不喜欢这种方法,因为我们不能在这样做的时候合并无点样式;/

  • 另一种方法是在匿名函数中调用hook,就像我在上面sn-p中写的一样。 - 虽然我们不必编写整个函数块并声明一个额外的变量,但我们也不喜欢这种方法,因为我们觉得我们一直都必须冗余地编写传递过来的参数:arg => hook()(arg)

在 FP 中是否有任何通用方法来处理我们必须注入函数的那种问题,该函数必须被延迟评估,然后基于该结果我们可以进行其他计算?也许甚至Ramda 本身也有这个函数,它有助于注入特定的行为,所以我们可以这样使用它:

R.evolve({
  title: R.useWith(useTranslate, R.identity) // arg => useTranslate()(R.identity(arg))
})

PS。我知道 Ramda 中有一个名为 useWith 的函数,但它的工作方式不同;/

我们将不胜感激任何帮助!

【问题讨论】:

    标签: javascript reactjs functional-programming react-hooks ramda.js


    【解决方案1】:

    我不确定我是否完全理解您的问题。您是否只是在寻找一种方法来对 useTranslate 进行一次初始化?如果是这样,那么我认为 Ramda 没有内置任何东西,但编写类似

    的东西就很容易了
    const dethunk = (fn) => {
      let initialized = null;
      return (...args) => (initialized || (initialized = fn())) (...args)
    }
    

    然后写类似的东西。

    const translateTitles = map (evolve ({title: dethunk(useTranslate) }))
    

    如果您想将参数传递给初始化,您可以将其更改为

    const dethunk = (fn, ...initialArgs) => {
      let initialized = null;
      return (...args) => (initialized || (initialized = fn(...initialArgs))) (...args)
    }
    
    const foo = (a, b) => {
      console.log(`Initializing with '${a}' and '${b}'`)
      return (c) => `foo('${a}', '${b}', ${c})`
    }
    
    const bar = dethunk(foo, 'x', 'y')
    
    console.log('Have not initialized yet');
    
    console .log (bar (1))
    console .log (bar (2))
    console .log (bar (3))

    这能满足你的需要吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-30
      • 2012-06-25
      • 1970-01-01
      • 2011-10-23
      • 2017-11-10
      • 1970-01-01
      相关资源
      最近更新 更多