我具有以下减速器功能
reducers的 first 参数是合计值,而 second 参数是下一个值。下面的reducer函数在相同的reaction
参数上进行归约,但聚合state$
值。每个化简函数都会产生一个新的合计值。
/**
* Applies all the reducers to create a state object.
*/
function reactionReducer(reaction: ReactionObject): ReactionObject {
let state$ = reactionDescriptionReducer({}, reaction);
state$ = reactionDisabledReducer(state$, reaction);
state$ = reactionIconReducer(state$, reaction);
state$ = reactionOrderReducer(state$, reaction);
state$ = reactionStyleReducer(state$, reaction);
state$ = reactionTitleReducer(state$, reaction);
state$ = reactionTooltipReducer(state$, reaction);
state$ = reactionVisibleReducer(state$, reaction);
return state$;
}
const state = reactionReducer(value);
上面的方法有效,但是该函数已通过化简器列表进行了修复。看来我应该可以使用RamdaJS进行类似的操作。
const state = R.????({}, value, [reactionDescriptionReducer
reactionDisabledReducer,
reactionIconReducer,
reactionOrderReducer,
reactionStyleReducer,
reactionTitleReducer,
reactionTooltipReducer,
reactionVisibleReducer]);
我是RamdaJS的新手,如果这是一个菜鸟问题,请原谅我。
如何仅使用RamdaJS执行一连串的减速器?
答案 0 :(得分:5)
and
通过组合两个(2)输入缩减器(r, x) => ...
和f
构造一个新的缩减器g
-
const and = (f, g) =>
(r, x) => g (f (r, x), x)
all
通过使用and
,通过组合任意数量的reducer来构造新的reducer-
const identity = x =>
x
const all = (f = identity, ...more) =>
more .reduce (and, f)
使用myReducer
定义all
-
const myReducer =
all
( reactionDisabledReducer
, reactionIconReducer
, reactionOrderReducer
// ...
)
给出这三(3)个reducer的模拟实现-
const reactionDisabledReducer = (s, x) =>
x < 0
? { ...s, disabled: true }
: s
const reactionIconReducer = (s, x) =>
({ ...s, icon: `${x}.png` })
const reactionOrderReducer = (s, x) =>
x > 10
? { ...s, error: "over 10" }
: s
运行myReducer
以查看输出
const initState =
{ foo: "bar" }
myReducer (initState, 10)
// { foo: 'bar', icon: '10.png' }
myReducer (initState, -1)
// { foo: 'bar', disabled: true, icon: '-1.png' }
myReducer (initState, 100)
// { foo: 'bar', icon: '100.png', error: 'over 10' }
展开下面的代码片段,以在浏览器中验证结果-
const identity = x =>
x
const and = (f, g) =>
(r, x) => g (f (r, x), x)
const all = (f, ...more) =>
more .reduce (and, f)
const reactionDisabledReducer = (s, x) =>
x < 0
? { ...s, disabled: true }
: s
const reactionIconReducer = (s, x) =>
({ ...s, icon: `${x}.png` })
const reactionOrderReducer = (s, x) =>
x > 10
? { ...s, error: "over 10" }
: s
const myReducer =
all
( reactionDisabledReducer
, reactionIconReducer
, reactionOrderReducer
// ...
)
const initState =
{ foo: "bar" }
console .log (myReducer (initState, 10))
// { foo: 'bar', icon: '10.png' }
console .log (myReducer (initState, -1))
// { foo: 'bar', disabled: true, icon: '-1.png' }
console .log (myReducer (initState, 100))
// { foo: 'bar', icon: '100.png', error: 'over 10' }
您可以为and
和all
选择任意名称。我可以将它们视为reducer
模块的一部分,例如reducer.and
和reducer.all
答案 1 :(得分:3)
我的第一次尝试根本不会涉及Ramda,只是一个简单的事情:
const makeReducer = (...fns) => (x) => fns .reduce ( (s, fn) => fn (s, x), {} )
const fn = makeReducer (
(state$, reaction) => ({...state$, foo: `<<-${reaction.foo}->>`}),
(state$, reaction) => ({...state$, bar: `=*=${reaction.bar}=*=`}),
(state$, reaction) => ({...state$, baz: `-=-${reaction.baz}-=-`})
)
console .log (
fn ( {foo: 'a', bar: 'b', baz: 'c'} )
) //~> {foo: '<<-a->>', bar: '=*=b=*=', baz: '-=-c-=-'}
答案 2 :(得分:3)
这里使用Ramda的一种选择是利用以下事实:它支持将函数作为monad实例传递给R.chain
(也称为Reader monad)。
这使您可以将共享某些公共环境的多个函数排序在一起-在您的情况下为reaction
。
我们可以利用R.pipeWith(R.chain)
来组成一系列这些需要一些输入的函数(例如,您的$state
穿过每个函数)并返回一个获取环境的函数,并产生结果传递给管道中的下一个功能。
// Some mock functions to demonstrate
const reactionDescriptionReducer = ({...state}, reaction) =>
({ description: reaction, ...state })
const reactionDisabledReducer = ({...state}, reaction) =>
({ disabled: reaction, ...state })
const reactionIconReducer = ({...state}, reaction) =>
({ icon: reaction, ...state })
// effectively `R.pipeK`
const kleisli = R.pipeWith(R.chain)
// we need the functions going into chain to be curried
const curried = f => a => b => f(a, b)
// finally, compose the series of functions together
const reactReducer = kleisli([
curried(reactionDescriptionReducer),
curried(reactionDisabledReducer),
curried(reactionIconReducer)
])({})
// and if all goes well...
console.log(
reactReducer("someCommonReactionValue")
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>