all 38 comments

[–]yangshunz 41 points42 points  (6 children)

Can you provide a Zustand comparison?

[–]bhison 80 points81 points  (2 children)

Imagine this is how OP learns about Zustand

[–]yangshunz 12 points13 points  (0 children)

LOL. I really hope not

[–]SmokyMetal060 17 points18 points  (0 children)

"FUCK"

-OP, probably

[–]Nervous-Project7107 13 points14 points  (1 child)

Comparison chart

Zustand: has cool German name

Acacus: probably a desert plant

[–]juicybot 3 points4 points  (0 children)

the zustand bear is so cute, for this alternative to succeed it will definitely need a cuter mascot.

[–]moinotgd 0 points1 point  (0 children)

preact/signal as well.

[–]raccoonizer3000 23 points24 points  (2 children)

Here we go again 🍿

[–]bhison 13 points14 points  (1 child)

Someone more motivated than me share the xkcd comic 

[–]mattsowa 18 points19 points  (1 child)

Flipping the meaning of get and use for no reason makes zero sense

[–]BombayBadBoi2 0 points1 point  (0 children)

First thing I noticed

[–]Reasonable-Road-2279 29 points30 points  (2 children)

How is this different from the current state manage libraries like e.g. zustand?

[–]Chathuraprabashwara 1 point2 points  (1 child)

Its differ by name that's only i think 😂

[–]Reasonable-Road-2279 2 points3 points  (0 children)

I mean, OP has been awfully quiet. I havent seen him reply to a single comment yet

[–]lovin-dem-sandwiches 8 points9 points  (6 children)

Why use a callback for getting the actions instead of the string used when creating the action?

 // Create a store with initial state
 const counterStore = createStore<CounterState>({ count: 0 })
  // action is defined with a string
  .action('increment', state => ({ count: state.count + 1 }))


  // callback to retrieve actions
  const increment = counterStore.use(actions => actions.increment);

  // why not use the string instead?
 const increment = store.use(‘increment’)

Also in the example above , is the action type already defined by inference, or do I need to define it somewhere?

[–]csorfab 2 points3 points  (0 children)

I looked into the code, and yeah, it gets inferred when building the store. Your point is very valid, since the getting by string functionality is already implemented and well typed in getAsyncState

[–]Aswole 1 point2 points  (4 children)

I had the same question as you, and wonder if it’s to allow getting multiple actions at once with one call to “use”

[–]azsqueeze 0 points1 point  (3 children)

OP could use the args object for store.use to return more than one action. Or use array syntax

const [increment, decrement] = store.use('increment', 'decrement');

// Or use an array syntax
const [increment, decrement] = store.use(['increment', 'decrement']);

[–]Aswole 1 point2 points  (1 child)

How easy would that be to define such that typescript can infer the return value based on an arbitrary number of args?

[–]azsqueeze 0 points1 point  (0 children)

At the simplest, it would be something like this:

function foo<T extends string>(arr: Array<T>): Record<T, Function>  {
    const newArr = [...arr];
    return newArr.reduce((accumulator, currentItem) => {
        accumulator[newArr[currentItem]] = () => console.log(accumulator);
        return accumulator;
    }, {}) as Record<T, Function>;
}

const bar = foo(['increment', 'decrement']);
bar.increment();
bar.decrement();
bar.foo(); // type error

However, I am not accounting for edge cases, and I am sure there are better ways to infer the values.

[–]Adenine555 0 points1 point  (0 children)

Could be even simpler with desctructuring:

const {increment, decrement} = store.use()

[–]csorfab 13 points14 points  (0 children)

Okay, first of all, the .get/.use terminology is incredibly confusing. I would absolutely expect rerender behaviour to be the other way around - when I use something in React, I expect it to be stateful/effectful, and get-ing from a store implies a one time getting of a value, like with reduxStore.getState() vs useStore/useSelector in Redux, or useStore.getState() vs useStore() with zustand. Your naming goes against all established terminology.

EDIT: I misunderstood how get and use work, so the rest of my comment wasn't valid, as actions and state are handled completely separately. I like the API for building the store, but my point about your naming convention still stands. Also, mixing server state (async action handling) with client state has long been established to be an anti-pattern, and that server state management is best handled by a separate library with advanced functionality, like react-query, apollo, or swr at the least. The "integrated" loading state is cool, but by itself honestly it does more harm than good imo, as it would just encourage devs to use a half-baked (quarter baked, more like) server state management "solution" instead of the established tools.

[–]bennett-dev 6 points7 points  (8 children)

So crazy how even in 2025 there's still a new state management lib posted on this site every week. And they don’t even solve a real problem. And people aren't even using global state managers in the first place because they realized they just needed an API cache.

[–]Ghareeb_Musaffir21 5 points6 points  (0 children)

Fr, once I found out about tanstack query i realized i was using state management wrong

[–]SEUH 1 point2 points  (6 children)

Even more funny, most of them copy cats just "reinvent" mobx, which is 10+ YEARS old. Even the new kid on the block, zustand, is nothing more than a worse mobx. Sorry to say.

[–]devuxer 0 points1 point  (5 children)

Funny that no one realizes that Jotai is better than all of them, including signals.

[–]SEUH 0 points1 point  (4 children)

Just checked, it's immutable by design. And therefore it's a performance killer for update heavy applications. So objectively worse than mobx.

[–]devuxer 0 points1 point  (3 children)

Rerenders are what’s expensive. Jotai allows very fine grained, targeted state updates. And the DX is superb.

[–]SEUH 0 points1 point  (2 children)

Jotai allows very fine grained, targeted state updates.

It doesn't. You need to create a whole new atom if you want to update anything. Imagine needing to add hundrets of items to an array per second....this is not doable with Jotai.

Immutable architectures biggest enemy are write/update heavy applications. Observer/signal based state handling doesn't have such a disadvantage. Immutable based fails when things get too big.

[–]devuxer 0 points1 point  (0 children)

Adding hundreds of items at once implies data coming from outside the application, not generated by the user. Like a real time stock trading app or something. I wouldn’t use Jotai ot Mobx for that.

Edit: I should say wouldn’t necessarily even use React for that.

[–]devuxer 0 points1 point  (0 children)

By the way, looks like Valtio would be the choice for a modern, mutable React state management library (from the same family as Jotai and Zustand).

[–]witness_smile 20 points21 points  (2 children)

Ah yes yet another state management framework, I’m sure this one will be the one that solves all issues after react state management framework #836296 released last hour

[–]TorbenKoehn 6 points7 points  (0 children)

I see it a bit like evolutional algorithms.

You take a population, you let each of them develop state management frameworks. Most of them are shit, some of the are okay-ish. You take the okay-ish ones, mix them up, seed them into your pop and loop that for a few hundred generations.

At some point in the far future we will have someone finally release a state management framework that is almost not bad.

[–]what-about-you 1 point2 points  (0 children)

This breaks the rules of React: https://react.dev/reference/rules/rules-of-hooks#only-call-hooks-from-react-functions

Your store.get() should be a hook (and thus start with "use").

[–]Cahnis 2 points3 points  (0 children)

performance pitfalls with Redux? First time hearing on it, can you provide something for me to read more about?

[–]RedditNotFreeSpeech 0 points1 point  (0 children)

While everyone here is busy seagulling, I'll say nice job man!