Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize storeUpdater Extensibility #163

Open
elbakerino opened this issue Dec 29, 2021 · 1 comment
Open

Optimize storeUpdater Extensibility #163

elbakerino opened this issue Dec 29, 2021 · 1 comment
Labels
Projects
Milestone

Comments

@elbakerino
Copy link
Member

elbakerino commented Dec 29, 2021

The general structure of storeUpdaterCreate storeUpdater with the options actionHandler/scopeUpdaterMap should be optimized to be easier extensible.

Currently some logic is hard wired inside scopeUpdaterMap, e.g. deleteOnEmpty in the scopeUpdaterValues and deleting valid when undefined in the scopeUpdaterValidity. These should be moved to a chain of functions, which can be added to the scopeUpdaterMap.

The storeActionHandler currently contains all store-action implementations, the reason why the storeUpdater historically needed to receive the oldStore, but together with the type=set action -> now not all store-actions need the oldStore - depending how the state is implemented. Thus the storeActionHandler should be split up and the storeUpdater should be more modular in general. e.g. allowing to "handle the set action for value scope without getting the oldStore.".

@elbakerino elbakerino added enhancement New feature or request refactoring core labels Dec 29, 2021
@elbakerino elbakerino added this to To do in ui-schema via automation Dec 29, 2021
@elbakerino elbakerino added this to the v0.4.0 milestone Dec 29, 2021
@elbakerino elbakerino changed the title Optimize storeUpdaterCreate Extensibility Optimize storeUpdater Extensibility Dec 30, 2021
@elbakerino
Copy link
Member Author

elbakerino commented Mar 16, 2022

With 0.3.0-alpha.11 it is now possible to fully overwrite and change the internal store handling - but it's not "pretty" atm. (there will be changes).

Can be used to individually overwrite:

  • any internal logic, like deleteOnEmpty
  • add new scope (todo: check typings for scope)
  • add new actions for onChange
  • use central logic when e.g. value is updated - and do not execute the actual store updater
import { UIStoreActionSet, UIStoreAction, UIStoreUpdaterData } from '@ui-schema/ui-schema/UIStoreActions'
import { scopeUpdaterMapDefault, createStoreUpdater, ScopeUpdaterMapType } from '@ui-schema/ui-schema/storeUpdater'
import { onChangeHandler, UIStoreType, UIStoreUpdaterFn } from '@ui-schema/ui-schema/UIStore'
import React from 'react'

// new custom action:
export interface CustomStoreActionElementDelete extends UIStoreAction {
    type: 'element-delete'
}

// all actions supported by custom reducer:
export type CustomStoreActions =
    UIStoreActionSet | CustomStoreActionElementDelete

// this map controls the `setter`/`getter` of the `storeKeys` position for each `scope`
const customScopeUpdaterMap: ScopeUpdaterMapType = {
    ...scopeUpdaterMapDefault,
    value: {
        // experimental, does not use `getter` and `setter` for that scope
        noStore: true,
    },
}

// the reducers must return the new data for the `storeKeys` position - except when `noStore` is on for the scope
// todo: typing/return type, especially in relation to `noStore` need to be optimized
export const storeActionReducers = <D extends UIStoreUpdaterData = UIStoreUpdaterData>(action: CustomStoreActions): UIStoreUpdaterFn<D> | D => {
    switch(action.type) {
        case 'element-delete':
            // todo: implement custom logic
            return {value: undefined} as D
        case 'set':
            // todo: implement custom logic
            return action.data as D
        default:
            // @ts-ignore
            throw new Error('storeActionReducers unsupported action: ' + (action.type))
    }
}

// bind the custom reducers and scope-setter/getter to the internal onchange dispatching
// todo: optimize typing for actions, somehow `extends` is required for IDE formatting there - but `extends` enforces wrong duck typing
// @ts-ignore
export const customStoreUpdater = createStoreUpdater<UIStoreType, CustomStoreActions>(storeActionReducers, customScopeUpdaterMap)

// binding the custom updater to create a new `onChange`
export const useCustomOnChange = (
    {
        setStore,
    }: {
        setStore: React.Dispatch<React.SetStateAction<UIStoreType>>
    },
) => {
    const onChange: onChangeHandler<CustomStoreActions> = React.useCallback((actions) => {
        setStore(customStoreUpdater(actions))
    }, [setStore])

    return onChange
}

I've built it with and around:

Reusable onChange bindings for Firebase/Firestore, which can split the value scope actions from all others. The value scope actions are then converted to update/updateDoc/delete/deleteDoc commands - converting the storeKeys to the doc-references and the to-be-patched properties of the document(s). Thus only supporting a limited amount of onChange as e.g. UIStoreActionUpdate is not possible to execute against firebase or firestore. The updates - which are consumed by listening for changes in firebase/firestore - are updating only parts of UIStore.values, thus controlled by fire and using noStore: true for value.

elbakerino added a commit that referenced this issue Mar 23, 2022
…pings #163

and normalize/optimize the GenericList widget html-structure and a bit of styling, very small sizing/gutter adjustments and better support for e,g. footer
@elbakerino elbakerino modified the milestones: v0.4.0, v0.5.0 May 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
ui-schema
  
To do
Development

No branches or pull requests

1 participant