fix: multiple computation lost reactive when track same reactive.
This commit is contained in:
parent
2a041e6e3d
commit
ecbe842154
|
@ -31,4 +31,4 @@ export {
|
|||
computed,
|
||||
isReactiveObj,
|
||||
untrack
|
||||
}
|
||||
};
|
||||
|
|
|
@ -26,7 +26,6 @@ export type State = typeof Fresh | typeof Check | typeof Dirty;
|
|||
type NonClean = typeof Check | typeof Dirty;
|
||||
|
||||
export interface RNodeOptions {
|
||||
root?: Root<any> | null;
|
||||
isSignal?: boolean;
|
||||
isEffect?: boolean;
|
||||
isComputed?: boolean;
|
||||
|
|
|
@ -17,7 +17,7 @@ import { isPrimitive } from './Utils';
|
|||
import { RNode } from './RNode';
|
||||
import { ProxyRNode } from './Types';
|
||||
import { RProxyNode } from './RProxyNode';
|
||||
import {getRNodeVal, getRootRNode} from "./RNodeAccessor";
|
||||
import { getRNodeVal, getRootRNode } from './RNodeAccessor';
|
||||
|
||||
export type Reactive<T = any> = RNode<T> | Atom<T>;
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ export interface RNodeOptions {
|
|||
isEffect?: boolean;
|
||||
isComputed?: boolean;
|
||||
isProxy?: boolean;
|
||||
parent?: RNode<any> | null;
|
||||
parent?: RProxyNode<any> | null;
|
||||
key?: KEY | null;
|
||||
equals?: (a: any, b: any) => boolean;
|
||||
}
|
||||
|
@ -55,8 +55,10 @@ export class RProxyNode<T = any> extends RNode<T> {
|
|||
this.key = options?.key as KEY;
|
||||
this.root = options?.root || {};
|
||||
|
||||
if (this.parent && !this.parent.children) {
|
||||
if (this.parent) {
|
||||
if (!this.parent.children) {
|
||||
this.parent.children = new Map();
|
||||
}
|
||||
this.parent.children.set(this.key, this);
|
||||
}
|
||||
|
||||
|
@ -109,7 +111,7 @@ export class RProxyNode<T = any> extends RNode<T> {
|
|||
return getRNodeVal(this);
|
||||
}
|
||||
|
||||
setValue(value: any) {
|
||||
setValue(value: T) {
|
||||
setRNodeVal(this, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ export function isPrimitive(obj: unknown): boolean {
|
|||
return obj != null && type !== 'object' && type !== 'function';
|
||||
}
|
||||
|
||||
export function isFunction<T extends (...prev: any) => any>(obj: unknown): obj is T {
|
||||
export function isFunction<T extends (...prev: any) => any>(obj: unknown): obj is Function {
|
||||
return typeof obj === 'function';
|
||||
}
|
||||
|
||||
|
|
|
@ -1,31 +1,66 @@
|
|||
import { reactive, computed, watch } from '../index';
|
||||
|
||||
describe('test reactive', () => {
|
||||
it('two signals, one computed', () => {
|
||||
it('computation should work with two reactive', () => {
|
||||
const a = reactive(7);
|
||||
const b = reactive(1);
|
||||
let callCount = 0;
|
||||
|
||||
const c = computed(() => {
|
||||
const product = computed(() => {
|
||||
callCount++;
|
||||
return { a: a.get() * b.get() };
|
||||
return { value: a.get() * b.get() };
|
||||
});
|
||||
|
||||
watch(() => {
|
||||
console.log(a.get());
|
||||
});
|
||||
// computed should be lazy
|
||||
expect(callCount).toBe(0);
|
||||
|
||||
expect(a.read()).toBe(7);
|
||||
|
||||
a.set(2);
|
||||
expect(c.a.read()).toBe(2);
|
||||
expect(product.value.read()).toBe(2);
|
||||
|
||||
b.set(3);
|
||||
expect(c.a.get()).toBe(6);
|
||||
expect(product.value.get()).toBe(6);
|
||||
expect(callCount).toBe(2);
|
||||
|
||||
expect(callCount).toBe(3);
|
||||
c.read();
|
||||
expect(callCount).toBe(3);
|
||||
product.read();
|
||||
// computed function should not be invoked
|
||||
expect(callCount).toBe(2);
|
||||
});
|
||||
|
||||
it('computations should be triggered when source is same reactive', () => {
|
||||
const pos = reactive({ x: 0, y: 0 });
|
||||
let xCalledTimes = 0;
|
||||
let yCalledTimes = 0;
|
||||
|
||||
const x = computed(() => {
|
||||
xCalledTimes++;
|
||||
return pos.x.get();
|
||||
});
|
||||
|
||||
const y = computed(() => {
|
||||
yCalledTimes++;
|
||||
return pos.y.get();
|
||||
});
|
||||
|
||||
expect(x.read()).toBe(0);
|
||||
expect(y.read()).toBe(0);
|
||||
expect(xCalledTimes).toBe(1);
|
||||
expect(yCalledTimes).toBe(1);
|
||||
|
||||
// when pos.x changed, x should be triggered and y should not
|
||||
pos.x.set(1);
|
||||
expect(x.read()).toBe(1);
|
||||
expect(y.read()).toBe(0);
|
||||
expect(xCalledTimes).toBe(2);
|
||||
expect(yCalledTimes).toBe(1);
|
||||
|
||||
// when pos.y changed, y should be triggered and x should not
|
||||
pos.y.set(1);
|
||||
expect(x.read()).toBe(1);
|
||||
expect(y.read()).toBe(1);
|
||||
expect(xCalledTimes).toBe(2);
|
||||
expect(yCalledTimes).toBe(2);
|
||||
});
|
||||
|
||||
it('reactive is a obj', () => {
|
||||
|
|
Loading…
Reference in New Issue