philipp-spiess / use-substate

🍙 Lightweight (<600B minified + gzipped) React Hook to subscribe to a subset of your single app state.
https://github.com/philipp-spiess/use-substate
MIT License
99 stars 1 forks source link

Proposal: Add trivial dispatch mapping functionality #2

Open raunofreiberg opened 5 years ago

raunofreiberg commented 5 years ago

Loving this library and it's simplicity so far. I'm just wondering why have you decided to expose dispatch directly instead of adding some trivial mapping of dispatch.

What I would love to see is:

Would love to hear your feedback on this :-) This doesn't seem to complicate the implementation that much and just allows you to write out your actions directly in the hook itself.

E.g:

const [substate, actions] = useSubstate(
    state => ({ count: state.count }),
    dispatch => ({
      increment: () => dispatch(increment()),
      decrement: () => dispatch(decrement()),
    })
  );

or

const [substate, actions] = useSubstate(
    state => ({ count: state.count }),
    { increment, decrement }
  );
philipp-spiess commented 5 years ago

Hey Rauno!

I don't think that action creator are a big improvement given that we would need to create them in the same function where we'd use them. For React Redux, those make more sense since the component itself does not need to be aware of Redux at all and can just call arbitrary props. However with this hook, the component is already aware that Redux is used so I don't think you would save a lot when creating action creators.

You can of course useCallback to create action creators regardless (see this example at the redux-react-hook package), or create a custom hook on top of useSubstate. Another alternative would be to use react-use-redux.

raunofreiberg commented 5 years ago

I'd think that the separation of concerns still applies in this case, regardless of the implementation being a hook rather than a HOC.

I still feel like when comparing the following two examples, the first one makes much more sense when thinking about where certain actions from. Especially if hooks are designed to sort of be called on the top level, I think having a proper mapping of dispatch to actions would really provide more encapsulated code.

Also, I'm not sure if there is a performance difference between declaring the action creators inside the hook vs. inline in the component?

function Counter() {
    const [substate, actions] = useSubstate(
        state => ({ count: state.count }),
        { increment, decrement }
    );

    return (
        <div>
            <h1>{substate.count}</h1>
            <button onClick={actions.increment}>+</button>
            <button onClick={actions.decrement}>-</button>
        </div>
    );
}
function Counter() {
    const [substate, dispatch] = useSubstate(
        state => ({ count: state.count }),
    );

    return (
        <div>
            <h1>{substate.count}</h1>
            <button onClick={() => dispatch(increment())}>+</button>
            <button onClick={() => dispatch(decrement())}>-</button>
        </div>
    );
}

Thanks!