couzic / lenrix

Type-safe, reactive, focusable redux store wrapper
MIT License
24 stars 1 forks source link

extract() #1

Closed couzic closed 6 years ago

couzic commented 6 years ago

Example:

const extract$: Observable<{a: A, c: C}> = store.extract({
   a: store.lens.focusOn('a'),
   c: store.lens.focusOn('b').focusOn('c')
})

extract$ only emits for new values of a or c

couzic commented 6 years ago

Alternatively:

const extract$: Observable<{a: A, c: C}> = store.extract({
   a: state => state.a,
   c: state => state.b.c
})
couzic commented 6 years ago

The second version is less type-safe, but more concise. Both alternatives are viable.

couzic commented 6 years ago

The second version (state selectors) would also support:

const extract$: Observable<{a: A, c: C}> = store.extract({
   a: state => store.lens.focusOn('a').read(state),
   c: state => store.lens.focusOn('b').focusOn('c').read(state)
})

Which is quite verbose. However, if the read() function was properly bound to the lens, we could do:

const extract$: Observable<{a: A, c: C}> = store.extract({
   a: store.lens.focusOn('a').read,
   c: store.lens.focusOn('b').focusOn('c').read
})

Which is way more concise. Anyway, it appears that binding functions to the lens would be most useful in many cases.

couzic commented 6 years ago

Binding reading functions to lenses is now an issue in immutable-lens: https://github.com/couzic/immutable-lens/issues/2

couzic commented 6 years ago

Due to TypeScript compilator type inference limitations, the version with selectors would actually look like:

const extract$: Observable<{a: A, c: C}> = store.extract({
   a: (state: State) => state.a,
   c: (state: State) => state.b.c
})

Which is not ideal either. Maybe another version using lenses should be considered:

const extract$: Observable<{a: A, c: C}> = store.extract({
   a: store.lens.focusOn('a'),
   c: store.lens.focusOn('b').focusOn('c')
})
couzic commented 6 years ago

Finally, extract() accepts both selectors and lenses