question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Remove actions from store for simpler API

See original GitHub issue

I am realizing I should have shared this idea earlier… now v3 is released so it’s a bit late… or is it?

The premise of this idea is that it’s always felt a bit odd to keep the actions themselves inside the store. I guess a dev might want to change the actions dynamically but I’d venture to say this is not happening in 99% of use cases.

So… I was playing with an idea of how I might be able to use zustand in a more casual way. I wanted to be able to easily lift my state from a local useState to a “global” zustand store. I tweeted about it here. Within that tweet there is a codesandbox with a playground exploring this idea.

The core idea of the playground is something like this:

// `globalState` uses zustand behind the scenes
const [useName, setName] = globalState('Tim')  // Store a simple literal
const [usePet, setPet] = globalState({ type: 'Cat', name: 'Nacho')  // Or store an object

const App = () => {
  const name = useName()
  const pet = usePet()  // could use a selector here if you want
  return (
    <div>
      // Call the setters from anywhere!
      <button onClick={() => setName('Bob')}>Change Name</button>
      <button onClick={() => setPet({ name: 'Beanie' })}>Change Pet Name</button>
    </div>
  )
}

So what did I learn from the idea?

That zustand stores are really about the data inside and subscribing to that data. The actions do not feel like they belong inside, they are just overhead. All that is really needed is exposing the set and get functions.

I realize this is all possible with v3 and you might be tempted to close this because of that reason, but I’m wondering if this mental shift should be more baked into the docs, or code, or both?

This is what I imagine it looking like (using the readme example). FWIW I love how v3 hangs additional methods on the hook, I also came to this conclusion recently.

import create from 'zustand'

const useCount = create(0) // Just provide the state, no actions

// Now, if you want create bespoke actions using the exposed useCount.set
// Side note: I think it should be called useCount.get() to get the state, just shorter and more elegant
const increase = () => useCount.set(state => ({ count: state.count + 1 })),
const reset = () => useCount.set({ count: 0 })

function Counter() {
  const count = useCount()
  return <h1>{count}</h1>
}

function Controls() {
  return <button onClick={increase}>up</button>
}

As you can see this simplifies the API greatly! Thoughts??

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:15 (8 by maintainers)

github_iconTop GitHub Comments

5reactions
timkindbergcommented, Aug 18, 2020

Thank you for all the consideration and suggestions on how I can use the v3 api. I think I am happy with the below as a compromise, which is possible with existing v3 api.

@zoontek Now that the setState (and getState) are available on the hook (and vanilla store) I will likely start to prefer to use those instead of adding actions to my store structure. And I’ll likely just use the hook version, even though it’s a bit odd to access the prototype methods it is also convenient enough for me to prefer it.

So instead of this

const useStore = create(set => ({ 
  some: 'state',
  actions: { someAction() { set(...) } }
}))
function App() {
  const { actions } = useStore(s => s.actions)
  actions.someAction()
}

I’ll be trialing this approach instead 👍

const useStore = create(() => ({ some: 'state' }))
const someAction = () => userStore.setState(...)
function App() {
  someAction(...) // No required boilerplate, can be called anywhere
}
2reactions
MonstraGcommented, Feb 16, 2021

Decided to use same approach, but also declare a namespace to organize it:

namespace SomeStore {
  export const useStore = create(() => ({ some: 'state' }))
  export const someAction = () => userStore.setState(...)
}
export default SomeStore;

function App() {
  const some = SomeStore.useStore(state => state.some)
  SomeStore.someAction() // No required boilerplate, can be called anywhere
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

Adding and Removing items from Redux store | by Rafael Cruz
This section of the blog will focus on how to remove a reminder from the redux store. You might have noticed that in...
Read more >
Stop using actions in Vuex | JavaScript in Plain English
There is a better place for “business logic” than the Vuex store actions. Write them into plain old functions and delete all your...
Read more >
filter - Delete item from data in reactjs and redux - Stack Overflow
const reducer · state = initialState, action · switch ; type) { case "ADD_MOVIE" · return ; favoriteMovies: [...state.favoriteMovies · payload · case ......
Read more >
Simple Redux Create Delete Contact Application - CodinGame
Step 2: We need to configure the Redux Store. First, we need to make three folders inside src directory. actions; reducers; store. To...
Read more >
Tutorial: Build a REST API with HTTP non-proxy integration
On the Lambda: Function list page, in the list of functions, choose the button next to GetPetsInfo, and then choose Actions, Delete. When...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found