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

Discussion: Accessing store from another store #44

Closed
timkindberg opened this issue Jun 30, 2019 · 2 comments
Closed

Discussion: Accessing store from another store #44

timkindberg opened this issue Jun 30, 2019 · 2 comments

Comments

@timkindberg
Copy link

Is it good or bad to have stores talk to each other? If it's ok, what would be good/bad ways of going about it? E.g. Here's one idea, if stores do use other stores, they could use the exposed API instead of the hook. I'm making this use-case up, so it might be unrealistic.

// UsersStore.js
export const [useUsersStore, usersStore] = create(...)

// CommentsStore.js
import { usersStore } from './UsersStore.js'

export const [useCommentsStore, commentsStore] = create(set => ({
  async loadUserComments(userId) {
    // Note: I'm accessing the other store here
    const commentIds = usersStore.getState().users[userId].commentIds
    set({ comments: await fetch(`/comments`, { ids: commentIds }) })
  }
}))

Or would it be better to force components to compose stores together like this?

// UsersStore.js
export const [useUsersStore] = create(...)

// CommentsStore.js
export const [useCommentsStore] = create(set => ({
  comments: [],
  async loadComments(commentIds) {
    set({ comments: await fetch(`/comments`, { ids: commentIds }) })
  }
}))

// Component.jsx
function UserComments({ id }) {
  // Note: I'm doing all the wiring together in the component instead
  const commentIds = useUsersStore(state => state.users[id].commentIds)
  const comments = useCommentsStore(state => state.comments)
  const loadComments = useCommentsStore(state => state.loadComments)

  useEffect(() => {
    loadComments(commentIds)
  }, [commentIds])
}

Maybe, if you really want to encapsulate the logic, you could create a custom hook to wire them together? We could export an additional non-zustand custom hook that joins two (or more) zustand stores together to provide composited functionality.

Would this even work? I think I like this...

// Not sure what file I'd put this in ¯\_(ツ)_/¯
export const useUserComments = (userId) => {
  const commentIds = useUsersStore(state => state.users[id].commentIds)
  const comments = useCommentsStore(state => state.comments)
  const loadComments = useCommentsStore(state => state.loadComments)

  useEffect(() => {
    loadComments(commentIds)
  }, [commentIds])

  return comments
}

// Component.jsx
function UserComments({ id }) {
  const comments = useUserComments(id)
}
@drcmda
Copy link
Member

drcmda commented Jun 30, 2019

both models are just fine. at work we're also doing a variant of # 3, creating specialized hooks that prime selectors to substate:

function useUser(sel) {
  const userId = useAppStore(state => state.activeUserId)
  return useUserStore(state => sel(state.users[userId]))

@dai-shi
Copy link
Member

dai-shi commented Aug 15, 2020

Look like resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants