如何在3个流之间共享startWith(false)
状态?我尝试使用withLatestFrom()
,但该值出现了一些奇怪的错误。
const Home = componentFromStream(prop$ => {
const { handler: toggleHandler, stream: toggle$ } = createEventHandler();
const { handler: showHandler, stream: show$ } = createEventHandler();
const { handler: hideHandler, stream: hide$ } = createEventHandler();
const modal$ = merge(
toggle$.pipe(
startWith(false),
map(() => prev => !prev),
scan((state, changeState: any) => changeState(state))
),
show$.pipe(
startWith(false),
map(() => prev => true),
scan((state, changeState: any) => changeState(state))
),
hide$.pipe(
startWith(false),
map(() => prev => false),
scan((state, changeState: any) => changeState(state))
)
);
return combineLatest(prop$, modal$).pipe(
map(([props, modal]) => {
console.log(modal);
return (
<div>
<button onClick={toggleHandler}>Toggle</button>
<button onClick={showHandler}>Show</button>
<button onClick={hideHandler}>Hide</button>
<h1>{modal ? 'Visible' : 'Hidden'}</h1>
</div>
);
})
);
});
在该示例中,toggle
不考虑show
或hide
的当前值,而仅考虑其最新值。
答案 0 :(得分:2)
为此,您将需要对状态进行一些不同的管理,类似于人们在redux中所做的事情。看一个例子:
const { of, merge, fromEvent } = rxjs; // = require("rxjs")
const { map, scan } = rxjs.operators; // = require("rxjs/operators")
const toggle$ = fromEvent(document.getElementById('toggle'), 'click');
const show$ = fromEvent(document.getElementById('show'), 'click');
const hide$ = fromEvent(document.getElementById('hide'), 'click');
const reduce = (state, change) => change(state);
const initialState = false;
const state$ = merge(
of(e => e),
toggle$.pipe(map(e => state => !state)),
show$.pipe(map(e => state => true)),
hide$.pipe(map(e => state => false)),
).pipe(
scan(reduce, initialState),
);
state$.subscribe(e => console.log('state: ', e));
<script src="https://unpkg.com/rxjs@6.2.2/bundles/rxjs.umd.min.js"></script>
<button id="toggle">Toggle</button>
<button id="show">Show</button>
<button id="hide">Hide</button>
要更好地了解其工作原理,请查看rxjs文档中的Creating applications文章
答案 1 :(得分:0)
首先在所有这些可观察值上具有startWith
意味着它们都将在开始时为false。就像您一次按下所有这些按钮一样。
我认为您应该尝试实现不同的行为。您想使用startWith
来设置modal
属性的初始状态,对吗?因此,应该在将这些流合并在一起之后出现。
要切换值,您需要做两件事:
scan
的累加器)这是我的方法:
const modal$ = merge(
show$.pipe(mapTo(true)),
hide$.pipe(mapTo(false)),
toggle$.pipe(mapTo(null))
).pipe(
startWith(false),
scan((acc, curr) => {
if (curr === null) {
return !acc;
} else {
return curr;
}
})
);
“显示”按钮始终发出true
,“隐藏”按钮始终发出false
,而切换按钮则发出null
。我将它们合并在一起,我们想从false
开始。接下来是scan
,它将状态保存在累加器中。
null
到来时它返回否定状态。当true
或false
出现时,它会返回它-这样,无论先前的值如何,它都会设置新的状态。
答案 2 :(得分:-1)
我采取了每个人的方法并提出了这个建议。它将toggle()逻辑保留在map函数内,并使用startWith()设置值。
const modal$ = merge(
toggle$.pipe(
map(() => prev => !prev),
),
show$.pipe(
map(() => prev => true),
),
hide$.pipe(
map(() => prev => false),
)
).pipe(
startWith(false),
scan((state, change) => change(state)),
);