-
Notifications
You must be signed in to change notification settings - Fork 139
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
useStore Hooks? #136
Comments
/**
* const [loggedIn, setLoggedIn] = useHookStore('loggedIn')
* console.log(loggedIn)
* @param {*} props
*/
export function useHookStore(prop) {
const selected = store.getState()[prop]
const setter = value => store.setState({ [prop]: { ...selected, ...value } })
return [selected, setter]
} example: import { useHookStore } from 'unistore'
const [ablySocket, setAblySocket] = useHookStore('ablySocket')
console.log(ablySocket) |
I like it! It'd be a little unfortunate to drop the action binding stuff though. Maybe something like this? import { createContext } from 'preact';
import { useState, useContext, useMemo, useEffect } from 'preact/hooks';
const StoreContext = createContext(store);
export const Provider = StoreContext.Provider;
function runReducer(state, reducer) {
if (typeof reducer==='function') return reducer(state);
const out = {};
if (Array.isArray(reducer)) for (let i of reducer) out[i] = state[i];
else if (reducer) for (let i in reducer) out[i] = state[reducer[i]];
return out;
}
function bindActions(store, actions) {
if (typeof actions=='function') actions = actions(store);
const bound = {};
for (let i in actions) bound[i] = store.action(actions[i]);
return bound;
}
export function useStore(reducer, actions) {
const { store } = useContext(StoreContext);
const [state, set] = useState(runReducer(store.getState(), reducer));
useEffect(() => store.subscribe(state => {
set(runReducer(state, reducer));
}));
const boundActions = useMemo(bindActions, [store, actions]);
return [state, boundActions];
} Usage: import { Provider, useStore } from 'unistore/preact/hooks';
const ACTIONS = {
add(state) {
return { count: state.count + 1 };
}
};
function Demo() {
const [state, actions] = useStore(['count'], ACTIONS);
return <button onclick={actions.add}>{state.count}</button>
}
render(<Provider value={store}><Demo /></Provider>, root); |
Another neat alternative would be to split the hooks into const ACTIONS = {
add: ({ count }) => ({ count: count + 1 })
};
function Demo() {
const [count] = useStoreState(['count']);
const add = useActions(ACTIONS.add);
// or to bind them all:
const { add } = useActions(ACTIONS);
return <button onclick={add}>{count}</button>
} |
That pattern would save some levels of nested components. @developit any plans on creating them? I'm right in the situation of refactoring App with hooks, that'd be a great help. I can come up with PR I guess. |
That pattern wouldn't support to preact 8.x right? so, we should be find solution for all versions, or something that work to separated versions. @developit you have any ideia about it? |
I was playing around with this tonight and came up with #153 I still can't figure out why I have ONE test failing, but it retains all the previous APIs while also giving us a hook and nearly all previous tests passing. Heavily inspired by @thadeu to make something that will feel familiar to anyone who used the old API Only downfall is that it will be a breaking change since it uses the new Context API Feedback welcome |
I'd like to add a suggestion about the API. Pre React Hooks it was typical to use a single connect command for a component, with multiple selectors and multiple actions per connect. I'm not sure this behaviour should carry over to hooks. Consumers can now use multiple hooks in a component. And this could be made possible by separating out selecting content from the store, With connect statement you might use something like: const mapStateToProps = state => ({user: getUserInfo(state), books: getBooks(state)})
const actions = [addBook, removeBook]
connect(mapStateToProps, actions) With Hooks you'd be able to pull these out to seperate commands: const userInfo = useSelector(selectUserInfo)
const books = useSelector(selectBooks)
const add = useAction(addBook)
const remove = useAction(removeBook) This potentially allows you to pull out common hooks such as |
@jahredhope You would be interested in https://github.com/facebookincubator/redux-react-hook |
Exactly @yuqianma . Aligning the API with Redux will help people moving between the frameworks. I had a crack at implementing it when I commented above, just a WIP:
Though the big win for me is the TypeScript type inference. Update: |
Would be lovely to get this in. I love this little library, but it's definitely missing support for hooks |
I created some hooks for Unistore based heavily on react-redux and redux-zero. Repo: https://github.com/mihar-22/preact-hooks-unistore I'd love some feedback and maybe integrate it into Unistore? |
All done @developit. I can keep it as a separate package or I can make a PR to pull it in and we can add it to |
Hey @mihar-22, I was following this thread and tried to use your proposal in my typical dashboard app that I'm porting from another framework. Apparently, I don't see how |
Hey @dkourilov, if you can raise the issue over at https://github.com/mihar-22/preact-hooks-unistore then I can try and help when I have a moment. If you can provide a little bit more information that'd help, thanks :) |
Are there any plans to go forward with official unistore react/preact hooks? |
Hope to see unistore and preact-hooks-unistore in a united package soon. |
Wouldn't install on Win10 for me :/ |
Used
@developit what do you think about this?
The text was updated successfully, but these errors were encountered: