diegohaz/constate

How to create selectors in order to listen on multiple changes in context's state?

saeidalidadi opened this issue · 2 comments

First of all, I should say thank you for your useful module. today I created a context's state and I tried to use a selector function that gets props names and returns a new state but it can't prevent unnecessary component renders. So is there any way to create such selector functions?

const init = { name: 'John', date: null }

const withReducerState = () => {
   const [state, dispatch] = useReducer(reducer, init)
   return {state, dispatch}
}

const [Provider, useContext, useName, useDate, useSelector] = constate(
     withReducerState,
     value => ({ state: value.state, dispatch: value.dispatch }),
     value => value.state.name,
     value => value.state.date,
     // Create a selector function that get an array of state props --- ['name', 'date']
     value => {
         return (selectors) => {
             console.log("$$$$$$$$$$$$$$$ selectors $$$$$$$$$$$", selectors)
             let state = {}
             for(let item of selectors) {
                state[item] = value.state[item]
             }
             console.log("$$$$$$$$$$$$$$$ selected state $$$$$$$$$$$", state)
             return state;
         }
     }
)

// In my Component I want to use the selector hook.
const MyComponent = () => {
    const {name, date} = useSelector()(['name', 'date'])

Constate currently doesn't support dynamic selectors like that. The static selectors are enough for most cases though, including the example you provided.

Do you have a real use case? Could you elaborate on that? It's possible that we'll support dynamic selectors in the future, but it'll add a lot of complexity to the library, so I'd like to make sure we have valid use cases first.

We know that our component will be re-rendered for changes of every state value inside the state object so if one component using multiple state values then we should expose any of them as hooks to prevent unnecessary renders due to changes of other values. so it would be a good thing to have an state selector to remove needing for define more state hooks.

const MyComponent = () => {
    const name = useName() // current 
    const otherValue = useOtherValue() // current
    
    // with selectors we may have these options
    const {name, otherValue} = useStore(state => state.name, state => state.otherValue)
    const {name, otherValue} = useStore()(['name'])
    const {name, otherValue} = useStore()(state => ({name: state.name, otherValue: state.otherValue}))
}