我和我的团队每天都在大力整合 FP 和 React-hooks 模式,尽管有时我们会为如何将 hooks 与纯函数一起管理而苦恼。最近,我们遇到了很多情况,其中钩子(Hook)“回调”必须位于 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
Hook 。不幸的是,我们不能在那里写 useTranslate()
,因为必须在挂载 React 组件后初始化 Hook 。到目前为止在这些情况下做了什么:
“即时”创建 Hook 函数,并将其传递给另一个 ramda 的函数。例如
{ const translate = useTranslate(); return R.compose(..., translate, ...) }
- 我们不喜欢这种方法,因为在执行此操作时我们无法合并无点样式;/另一种方法是在匿名函数中调用 hook,方法与我在上面的代码片段中所写的相同。 - 虽然我们不必编写整个功能 block 并声明一个额外的变量,但我们也不喜欢这种方法,因为我们觉得我们总是不得不冗余地编写传递过来的参数:
arg = > 钩子(Hook)()(参数)
在 FP 中是否有任何通用方法来处理我们必须注入(inject)函数的问题,该函数必须被延迟评估,然后我们可以根据该结果进行其他计算?甚至 Ramda
本身也有帮助注入(inject)特定行为的功能,所以我们可以这样使用它:
R.evolve({
title: R.useWith(useTranslate, R.identity) // arg => useTranslate()(R.identity(arg))
})
附言。我知道 Ramda 中有一个名为 useWith
的函数,但它以不同的方式工作;/
我们将不胜感激任何帮助!
最佳答案
我不确定我是否完全理解您的问题。您是否只是在寻找一种仅对 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))
这是否满足您的需求?
关于javascript - 将自定义 Hook 注入(inject) evolve 函数的优雅方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58155062/