Replies: 3 comments
-
so far i came with this, which does the job but im not sure about possible performance impacts of running this code on every state change reaction(this.state, ['isPlaying', 'progress.position'], ([isPlaying, position]) => {
console.log(isPlaying, position);
});
export const reaction = <S extends object, K extends Paths<S>[]>(
state: S,
keys: [...K],
action: (results: RemapKeysToState<S, [...K]>) => void,
) => {
let changed = false;
const values: Map<string, NestedValueOf<S, Paths<S>>> = new Map();
return subscribe(state, () => {
keys.forEach(key => {
const props = key.split('.');
let value: any = state;
props.forEach(prop => {
value = value[prop];
});
if (values.get(key) !== value) {
changed = true;
values.set(key, value);
}
});
if (changed) {
action(Array.from(values.values()) as RemapKeysToState<S, [...K]>);
changed = false;
}
});
};
type RemapKeysToState<S extends object, T extends Paths<S>[]> = {
[K in keyof T]: NestedValueOf<S, T[K]>;
};
type Paths<T> = T extends Array<infer U>
? `${Paths<U>}`
: T extends object
? {
[K in keyof T & (string | number)]: K extends string ? `${K}` | `${K}.${Paths<T[K]>}` : never;
}[keyof T & (string | number)]
: never;
type NestedValueOf<Obj, Key extends string> = Obj extends object
? Key extends `${infer Parent}.${infer Leaf}`
? Parent extends keyof Obj
? NestedValueOf<Obj[Parent], Leaf>
: never
: Key extends keyof Obj
? Obj[Key]
: never
: never; |
Beta Was this translation helpful? Give feedback.
0 replies
-
Valtio isn't designed to be a mobx replacement from the beginning, and "reaction" is one of such features that are excluded by design. |
Beta Was this translation helpful? Give feedback.
0 replies
-
import { proxy, snapshot, subscribe as _subscribe } from "valtio/vanilla";
// ...
export interface State {
// ...
}
export const state = proxy<State>({
// ...
});
export const subscribe = <T>(
selector: (state: State) => T,
cb: (v: T) => void
): ReturnType<typeof _subscribe> => {
let oldValue = selector(snapshot(state) as State);
return _subscribe(state, () => {
const newValue = selector(snapshot(state) as State);
if (oldValue === newValue) return;
oldValue = newValue;
cb(selector(state));
});
}; this should do the trick |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
seems like a core piece of functionality is missing – i need to track a primitive change in vanilla inside a deeply nested proxified state, but it seems to be impossible with valtio.
subscribeKey
only works on root level properties of a proxy,subscribe
doesn't work on primitives, and so doeswatch
. Any idea how mobx does it with theirreaction
/autorun
? It would be extremely useful.Beta Was this translation helpful? Give feedback.
All reactions