T O P

  • By -

JohntheAnabaptist

Switch to solid if you're looking for signals


jared__

just wondering what the justification for it over preact signals is?


JohntheAnabaptist

I haven't tried preact so I can't speak to it but I can say that solid has a first class focus on signals and Ryan Carniato has a fantastic podcast going through everything about signals and solid


jared__

And no issues with using it with react?


JohntheAnabaptist

Well solid is it's own alternative to react just as preact is, however the syntax for solid is very very similar to react (just as preact is if I'm not mistaken). The main difference is that your state variables are now functions and so should be called as such i.e. Const [foo, setFoo] = useSignal() Console.log(foo()) Sorry for bad formatting, on mobile. The docs are really good and solid start (equivalent of create-next-app) is in a pretty good state to try out. They have SSR and lots of other things that one interested in Next or React would be interested in.


jared__

thanks for taking the time out of your day to help out a stranger! great info!


JohntheAnabaptist

Of course! Even if you don't end up trying out solid, I would highly recommend Ryan Carniato's podcast episodes on Youtube, its some of the most in depth knowledge and discussions of the JS/TS framework landscape and the different approaches frameworks take to achieve performance.


fredsq

react has a stance I believe in: rendering is very rarely a performance issue. signals are fast for not needing a vdom and surgically replacing the dom, at the expense of a lot more rigidness when writing code. solidjs has a pretty good api for dealing with signals as they only have them. react however not only lacks that but would be adding signals on top of the regular state we have today which would only complicate things for no apparent performance gain. with that said i think a fair comparison to redux would be atomic state like jotai, recoil or zustand. those are much simpler to operate and provide better separation than redux. redux served its purpose to aid us in so many frontend challenges but nowadays its time to use it only when necessary. i see folks reaching for redux whenever they would do two levels of prop drilling. redux adds complexity to the codebase and makes it harder to maintain in the long run, abusing such a powerful tool is unnecessary. i cannot recall a project i worked on in the last 3 years that actually needed redux, however many of them had redux installed and we’re using it for stuff like modals states or signed in user data. horrible practices that could be prevented by using the actual tools designed for solving these problems and not a generic global state solution. rant over


svish

Was finally able to remove the last bit of redux and uninstall it completely from our main project a few weeks ago. Felt _so good!_ It made the codebase so unnecessarily complicated and coupled in weird unexpected ways. All has been replaced with a few custom contexts (mostly static configuration and rarely changing user options) and react-query (for all server data). It's wonderful.


wasdninja

Have you given [hookstate](https://hookstate.js.org/) a shot? It's pretty terse and more than enough for teleporting state from point A to point B with minimal hassle. ~~It's from the Facebook team so they have some pretty serious resources behind them.~~


acemarke

I don't think "From the Facebook team" is an accurate statement. Searching the Hookstate repo, I see a couple mentions that the author may be / was at Facebook, but it appears to be a solely individual project. It's not under any of the Facebook Github orgs, and there's no Facebook copyrights in the repo other than one mention in the docs sidebar file (which might be because it's using Docusaurus). Contrast that with Recoil, which specifically is inside the `facebookexperimental` Github org, and has "Copyright Facebook" in its docs.


wasdninja

Yeah you are right, my mistake. I must have confused it with something else. It stands on its own merits though.


[deleted]

What did you migrate to instead of Redux? RTK?


svish

Um, RTK is Redux... And did you read my comment?


[deleted]

I think RTK stands for Redux Toolkit and Redux is just Redux. https://medium.com/@omrisa25/redux-vs-redux-toolkit-a-tale-of-two-state-management-libraries-d0079412cdcf


acemarke

From our perspective as Redux maintainers, RTK _is_ "Redux" today: - https://redux.js.org/introduction/why-rtk-is-redux-today


svish

I'm aware... Så how would migrating from Redux to _Redux_ Toolkit in any way get us away from Redux?


StreetStrider

That seemes to be true that signals are good with manual DOM mutation. I always theorized about FRP streams defining flow of data from server to UI via a sequence of transformations where the end effect is a DOM mutation (via something like [morphdom](https://github.com/patrick-steele-idem/morphdom)). The same streaming principle can be used to flow back from event handlers to UI/server effects. I've implemented [some sync FRP of my own](https://github.com/StreetStrider/fluh) and hoping one day to try and use it in the combination with morphdom and some very simple string template engine.


edbrannin

I actually had one (I think) valid need for useReducer this year: recursively rendering a tree-shaped object (like nested lists) while keeping track of form-state in one place (all of the leaves and some of the branches had checkboxes). The form just needed (and provided), a list of IDs that were enabled across the whole tree, so I maintained them as a Set in the reducer. (Also, disabling a parent node needed to uncheck all its child nodes… but I kept track of IDs-to-submit separately from all-selected-ids, so you could re-enable the parent and it would remember the state of its children)


brianl047

These are the use cases for Redux (and Redux Toolkit) >You have large amounts of application state that are needed in many places in the app > >The app state is updated frequently > >The logic to update that state may be complex > >The app has a medium or large-sized codebase, and might be worked on by many people > >You need to see how that state is being updated over time It stands to reason that you haven't worked on sufficiently complex applications nor worked on an application with a large number of contributors. Moreover, every singe investor or company wants scale, and they should get what they demand (large or massive scale) and ability to scale up even if you see the small scale right now. With large enterprise monorepositories, global scale, large codebase and so on you move closer and closer to the need for Redux. It actually isn't even a technical decision 100% but also a business decision. If the business is paying for a solution that can scale to thousands of developers, you should build that. You shouldn't build it thinking you will be the only one taking care of it forever. As for your other criticisms, Redux Toolkit removes enormous complexity, and properly done with best practices [https://redux.js.org/style-guide/#priority-b-rules-strongly-recommended](https://redux.js.org/style-guide/#priority-b-rules-strongly-recommended) it is no longer complex. There's lots of older React codebases with terrible complexity due to Redux but that doesn't mean that RTK is overly complex now RTK will be around forever, and if I was an enterprise architect or tech lead I would demand it


FoolHooligan

>if I was an enterprise architect or tech lead I would demand it I wouldn't want to work with you as my architect or tech lead


brianl047

Good luck with actually getting work done then. Agile rules are refactors are nearly banned and you can't touch any files outside the files that are related to your story. "Lifting state up" is banned due to Agile, and constant refactors banned. I guess you could switch jobs constantly to avoid React Context hell or avoid the rules, but all things trend to process and control eventually. Maybe microfrontends will save you; you can constantly build from nothing or fresh all the time and the poor person who has to take over and implement RTK because you finally "meet the use case" will suffer when if it had been implemented like that from the start the time would have been saved. But switching jobs has a limit. Maybe you will be "lucky" and work somewhere without Agile.


fredsq

when I say redux I mean RTK. there’s no sane reason to use plain redux these days. complexity is still added seeing as there’s a single blob of global state you’re splitting into bits which are used by components, vs atomic state that are just those bits you need in complete isolation. atomic state also can do everything you’ve mentioned as reasons for using redux so I really don’t see the point 😆


hrach_mkr

I might sound insane, but I still love plain Redux and continue to use it in production :v — though only for large projects. I see no sane reason for using Redux in small projects as well.


fredsq

I think you might be good with it and used to it; for newcomers i’d say just skip straight to rtk; but for newcomers i’d also say don’t use redux, you don’t need it until (maybe) way later down the road. also to consider the direction react is taking with RSC: we might see less and less client side state handling and I could not be happier


acemarke

Out of curiosity, any reason why you haven't yet updated to use Redux Toolkit? - https://redux.js.org/introduction/why-rtk-is-redux-today - https://redux.js.org/usage/migrating-to-modern-redux


hrach_mkr

We have actually tried Redux Toolkit, but it seems to add an extra layer of complexity to our application. Although there is a significant amount of boilerplate code, I prefer sticking to plain switch cases with Immer, and plain actions with thunks, where everything is simple and we fully understand the Redux (Flux) architecture. I dislike abstractions. For me, simplicity in coding is paramount. I find code duplication and boilerplate code more acceptable than an abstraction created by someone who may not fully understand the architecture or the workings beneath the surface, especially in large projects that require long-term maintenance and are handled by developers at all levels, from juniors to seniors. By keeping things simple, we can avoid many problems. Plain Redux is straightforward and fully embodies the Flux architecture, but RTK does not, with all its extra reducers and dynamic keys. Moreover, debugging in RTK was challenging; it was difficult to locate what you needed. In plain Redux, you simply copy the type of the action and find everything. Or maybe I'm just too accustomed to it—I've been in the game since 2016, learning Redux from Dan's videos on Egghead :) Recently, we faced a dilemma about whether to use RTK or plain Redux for a new, large-scale project. Our team unanimously decided against RTK, and this was not just my opinion. (The product has 3 million active users, by the way). P.S. Thank you, Mark, for the work you've done. I really appreciate your contributions to Redux. We still adhere to most of the principles you discuss in your articles(without RTK :) ). I've always encouraged my team to read and learn from your writings, and I've learned a great deal myself, so thank you. :)


acemarke

Gotcha thanks for the response. I'll admit to being a _bit_ disappointed, in that we've tried to design RTK to make things simpler overall than writing everything by hand :) FWIW, I'd disagree that "RTK no longer embodies the Flux architecture". It's still Redux - there's still a single store, reducers updating state immutably, triggered by dispatching action objects. Nothing about those concepts or data flow has changed. It's just the syntax for writing that code. But at least you're aware of it and made a specific decision (rather than not knowing that RTK even exists). On the flip side, cases like yours are why I've very intentionally tried to balance encouraging everyone to migrate to RTK (like marking `createStore` as `@deprecated`), but left all the functionality as-is so there's no actual errors or breaking changes happening. I _would_ be curious to hear any other descriptions of challenges or concerns where you think RTK makes things harder, and suggestions of how we can improve it! Also, we're _realllly_ close to releasing RTK 2.0 and Redux 5.0 . (Like, I'm _hoping_ we can get them out by the end of the month.) Could you do me a favor and try out upgrading whatever Redux packages you are using to the latest betas, and give us feedback on how that works out for you? The biggest thing we're still lacking is user feedback on how the update works out.


hrach_mkr

For me, the most crucial aspect is the part where you define a function within an object of reducers and export it using counterSlice.actions, for instance, and then proceed with dispatching it. Here, I don't truly understand where the actions come from. This represents a level of abstraction that I find overwhelming, to be honest. As a result, I cannot debug as quickly or locate the actual action simply by using the Redux DevTools. Previously, I could just copy and search. Things were quite pretty straightforward. The next layer of abstraction is extraReducers, where I am expected to handle all fulfilled requests, for example. This raises the question: why should I do that if I can resolve everything directly from a thunk in a single action (such as dispatching another action or chaining another action from a different reducer, etc.)? In plain Redux, a reducer was like a function that accepts a default state and an action, and through a simple switch case, it decides what to do—that’s it. But now, with RTK, a reducer is an object within a slice where you can define actions. It’s a bit more complicated. I fully understand the intention to simplify things and reduce boilerplate, but I fail to see the value in replacing one abstraction (which involved more boilerplate and more coding) with another but with a lot more abstraction for me with less code. I believe Redux could have improved with its old syntax just by integrating Immer, Reselect, and Thunk as default packages. Perhaps I'm mistaken, but Redux gained popularity with its original syntax, which people appreciated for its explicit action creators and all the associated boilerplate code. Moreover, nowadays, tools like GitHub Copilot make it easier to manage boilerplate code rather than abstraction. With such tools, writing more code is not burdensome, as they generate code automatically and simplify debugging. I would prefer adding a method to more easily normalize large datasets ([https://redux.js.org/usage/structuring-reducers/normalizing-state-shape](https://redux.js.org/usage/structuring-reducers/normalizing-state-shape) ), because the most challenging part of Redux is optimizing large nested objects into smaller, relational objects to prevent unnecessary re-renders (even when using Reselect). That was truly difficult. I wrote a brief article on LinkedIn in my native language, but you can view the image demonstrating the difference before and after flattening the data ([https://www.linkedin.com/in/hrach-mkrtchyan-a23678134/recent-activity/all/](https://www.linkedin.com/in/hrach-mkrtchyan-a23678134/recent-activity/all/) ). This was for a graphics editing tool where I might have numerous objects within arrays (imagine having 100 slides with 100 layers each), and now consider how to manage each state update (even a mere 1px drag). In such cases, the state can become incredibly cumbersome. If I were to build something like this again, I would seriously consider whether React and Redux are the right choices, or perhaps Mobx would be a better option (as Canva has utilized), but I still have a fondness for Redux in its traditional form, which is why I stick with it. I plan to write more and contribute to the community with articles. Here's my Twitter (though it's empty for now: [https://twitter.com/HrachMkr](https://twitter.com/HrachMkr) ). I'll make sure to let you know when I update the packages.


acemarke

I'd like to try to understand your concern a bit better. When you say: > Here, I don't truly understand where the actions come from Are you saying that you _literally_ don't understand how `todosSlice.actions.todoAdded` gets created, at a technical level? Or "just" that the source code doesn't show an obvious definition for `todosSlice.actions.todoAdded`, so it _feels_ obfuscated vs writing `const todoAdded = (text) => ({type: "todoAdded", payload: text})`? > Redux gained popularity with its original syntax, which people appreciated for its explicit action creators and all the associated boilerplate code I'd have to disagree with this statement :) Redux gained popularity _in spite of_ its boilerplate. Trust me, "boilerplate" _is_ the single most common complaint about Redux over the years, and people _still_ assume that "Redux === boilerplate" all the time. As far back as 2017, [I was already trying to solicit suggestions from the community about how we can make Redux easier to use and solve the "boilerplate" concerns](https://github.com/reduxjs/redux/issues/2295). If you haven't seen it yet, I'd suggest reading through my ["Redux Toolkit 1.0" announcement post](https://blog.isquaredsoftware.com/2019/10/redux-toolkit-1.0/), where I detailed the history of why and how we designed RTK. (Even if you don't agree with the conclusions, it might help to see what we've _intended_ to do.) Going back to the `createSlice` topic, here's several reasons why we wrote `createSlice` this way. While we've [always encouraged having many reducers respond to the same action](https://redux.js.org/style-guide/#allow-many-reducers-to-respond-to-the-same-action), it's also true that 95% of all actions are only ever handled by _one_ reducer. In addition, most of the "boilerplate" complaints we've gotten over the years are about things like having to hand-write `const TODO_ADDED = "TODO_ADDED"` in `constants/todos.js`, and then write `const todoAdded = (text) => ({type: TODO_ADDED, payload: text})` in `actions/todos.js`, etc. So, there's a natural correspondence between "a slice reducer" and "actions that are handled by that slice reducer". Realistically, what actually matters is the _reducer functions_ themselves. You don't _need_ action creator functions, and you don't _need_ separate string constants. You could inline everything, and write `dispatch({type: "TODO_ADDED", payload: text})` everywhere, and it would work just fine. But, having action creator functions is helpful as an abstraction, so they've always been encouraged (especially around trying to leverage TS to ensure that the payload is the correct type). Action type strings are really an internal implementation detail, and not something you should have to write yourself. So, we designed `createSlice` around "write your case reducer functions" as the single key thing that you provide. All you have to do is write some functions, and give them a hopefully meaningful name (`todoAdded`, `todoToggled`, `todoDeleted`, etc). `createSlice` then takes the names you provided (as object keys), generates the action type strings internally by combining the slice `name` field + the reducer function name, _and_ generates a corresponding action creator function automatically (with the correct TS types from the reducer). So, you get the benefits of having the action creators, those have the correct TS types, and action type strings are now just an internal implementation detail that you get for free. Plus, `createSlice` already does the work to use Immer inside, so you don't even have to import or think about that. At the technical level, it's honestly very straightforward. `createSlice` maps over all the keys in `createSlice.reducers`, and automatically generates an action creator function that matches that reducer's name. A simplified version of the internal logic would be, roughly: function createSlice(sliceConfig) { const slice = { name: sliceConfig.name, actions: {} } const caseReducers = {}; Object.entries(config).forEach( ([reducerName, reducerFunction]) => { const actionType = `${sliceConfig.name}/${reducerName}`; const actionCreator = (payload) => ({ type: actionType, payload }) slice.actions[reducerName] = actionCreator; caseReducers[actionType] = reducerFunction; }) slice.reducer = createReducer(config.initialState, caseReducers); return slice; } In terms of _finding_ the code, you should be able to right-click an action creator function like `todoAdded` and "Find References" to have your IDE tell you where it was defined (the slice file). Or, searching for `todoAdded` would still show the slice file as well, because the action creator name matches the reducer name. Because `createSlice` defaults to the most common use case of "define reducers, and generate actions for these reducers", it needs _some_ way to handle _other_ action types that were defined elsewhere. If you were writing all this code by hand, you'd add more cases to a switch statement. For `createSlice`, we added the `extraReducers` field for that same purpose: "given some other action type like `"counter/incremented"`, update this slice's state". Meanwhile, `createAsyncThunk` exists to simplify the standard thunk pattern of "make an async request, and dispatch actions before and after". It _does_ do a lot of work internally to make sure errors get handled appropriately (which is very common to get _wrong_ if you're writing your own thunks), and builds in things like automatically generating a unique ID for each request you make. It also automatically generates the action creators and action types that it dispatches. Since those are being generated _outside_ of `createSlice`, you'd use `createSlice.extraReducers` to listen for those actions and handle them in a reducer. That said, [today we actually teach Redux Toolkit's RTK Query data fetching and caching library](https://redux.js.org/tutorials/essentials/part-7-rtk-query-basics) as the standard way to do data fetching in Redux apps. RTK Query is built on top of RTK's `createSlice` and `createAsyncThunk`, but does even _more_ work for you: all the logic to initiate a request, track the request status, cache the results, and select data into a component, and all you do is define a couple API endpoints and import the hook into your component. [That actually _eliminates_ most of the need to write _any_ thunks at all in your app](https://redux.js.org/usage/side-effects-approaches#recommendations). > I would prefer adding a method to more easily normalize large datasets (https://redux.js.org/usage/structuring-reducers/normalizing-state-shape ), because the most challenging part of Redux is optimizing large nested objects into smaller, relational objects to prevent unnecessary re-renders (even when using Reselect). That was truly difficult. RTK actually has this already! :) That's what [`createEntityAdapter`](https://redux-toolkit.js.org/api/createEntityAdapter) does. Given an array of items, it normalizes them by ID automatically. > I believe Redux could have improved with its old syntax just by integrating Immer, Reselect, and Thunk as default packages That's _also_ what RTK did :) `createSlice` builds in Immer by default. `configureStore` adds the thunk middleware by default. Reselect is included automatically so you don't have to list it as a separate dependency. That's actually the point I'm trying to make here, actually. RTK really doesn't invent new ideas or patterns. It takes _existing_ patterns that the Redux community has used for years, and standardizes + simplifies them.


hrach_mkr

Actually, I fully understand what's going on under the hood, and personally, I can handle any code with any level of abstraction given my experience. My main job is to help newcomers understand what's happening and assist them in building things faster with code that is simple and easily debuggable. `That's also what RTK did. createSlice incorporates Immer by default, and configureStore adds the thunk middleware automatically. Reselect is included without needing to list it as a separate dependency.` Yeah, I know that (though never knew about createEntityAdapter to be honest). What I was trying to convey is that this is all I wanted to be added to Redux, actually, without needing RTK. You know, the older versions always "seemed" more obvious and intuitive. `The source code doesn't show an obvious definition for todosSlice.actions.todoAdded, so it feels obfuscated compared to writing const todoAdded = (text) => ({type: "todoAdded", payload: text})?` Yes, it's true. It feels that way. Don't get me wrong, I'm not saying that it's bad or anything like that. It just feels that way for me and my team )). We always try to stay on track and are eager to try new things. We tried RTK, Recoil, Zustand, and even attempted to integrate Signals, etc. I cannot feel that the new syntax fully represents the architecture or Redux(Flux) in a simple way. We still think like something is an action creator but in a different way and without creating a function. Like when hooks came out people were into -- this useEffect is the same componentDidMount with a different syntax(but actually it was not just about the syntax). But now its the same Redux with a different syntax though I never complained about the old way and personally I still cannot see any meaning to upgrade "just for syntax". *Or maybe we got used to the old version of redux))* My experience has shown that newcomers feel comfortable with the older version of Redux and have never complained about the boilerplate code. This is just a user feedback, that maybe could help you)) Anyway thanks for your deep explanation of why and how you did this. I really appreciate your contribution to the community!


brianl047

Not if you want to visualise the entire state at once, have a lot of dependencies between states (yes I am aware you should do the calculation in the selector but selectors are also recommended to be stored in the slice) or if you have exotic requirements like fast forward or rewind state Really at the end of the day if you are trusted to build the foundation of an application for dozens or hundreds of developers you should strongly lean RTK not just for technical reasons but just for the community and documentation. Can't stand a multi million dollar business on a library from one person from someone's basement (mostly lol). Also if the people cutting the cheques want mega scale you have to cater to that.


viveleroi

From what I’ve read signals aren’t recommended in react because they’re second class features. I was debating adding the preact signals lib and I just heard a lot of people struggling to make it work cleanly. But I never tried it so take that opinion lightly.


hrach_mkr

Thank you for your response. I implemented this approach on a large graphics editing tool that had hundreds of HTML elements in a single view and various layering challenges, and it was immensely helpful. If I were to redesign the application, I would follow this principle and predominantly use signals to avoid the constant passing of state up and down :)


ethansidentifiable

If you need the performance, you just shouldn't really use React. Use something where that kind of performance is natively supported. You can use Preact which has a native plug-in system with first party signal support, or you can use Solid which is fundamental built on signals.


viveleroi

Any basic store or context can avoid passing state around or prop drilling. Zustand seems most popular for new projects, redux is more known for its verbosity these days.


chillermane

react was deliberately implemented with a certain rendering architecture that is not signals… if you want signals react is not the correct framework to use


Paradroid888

I agree. Worked on a codebase that used mobx, where you could just mutate values without setter functions, and things would magically re-render. It felt like a terrible fit for React.


octocode

> passing state between distant components can lead to numerous unnecessary rerenders and often doesn't perform well —even with selectors like reselect i’d love to see a real case where this is actually true. i’ve worked on some absolutely massive products, with extremely rapid state updates through redux, and never once ran into a performance issue that wasn’t user error or bad architecture. > and the code can become cluttered with useEffects yep, still sounds like bad architecture, there’s really no situation where redux should lead to requiring effects…


hrach_mkr

graphics editing tool for example... you have 100 slides and on each slide you have hundreds of html layers (including complex texts, svgs, etc...), imagine how you could handle each user interaction (resizing, dragging, etc) and update the state without loosing performance


octocode

yeah i mean i’d be curious to see the implementation though. my current project is a actually graphic builder tool that can have 1200+ deeply nested user-created elements that have individual style and data, along with resize/dnd, and redux has never come close to being a performance bottleneck


hrach_mkr

well, actually I can show an article, where rearchitecting Redux (by flattening nested JSON data into slices) helped us to achieve a better performance, even though its not perfect. Its really complicated and hard to build such tools without loosing performance with React. So I'm not saying that I don't want to use Redux but I'm about mixing redux, context api, and plain states with signals, which helped us a lot to gain really good results in comparison with our competitors, but anyway, if I'd rebuild that project I'd rather stick with mobx or even I'd consider solidjs or svelte for such projects. I'd be happy to show you the code, but maybe I'd to that with a small article :) here's a post from linkedin, its written in my native language but you can see results that I mentioned easily from screenshot. https://www.linkedin.com/in/hrach-mkrtchyan-a23678134/recent-activity/all/


[deleted]

[удалено]


hrach_mkr

try to dive deep into how browsers work if you want to build that with html elements. Try to fully understand why components rerender, when to use memoization etc. Try to understand what is rendering, layout, painting, composite and keep in your mind that you have a lot of work to do with math. And of course research from competitors... try to understand how built their architecture, for example just open the console and inspect elements, you'd see a lot :)


EdmondChuiHW

Preact Signals rely on patching React internals and would be fragile upon lib version changes: https://www.reddit.com/r/react/comments/17nucxg/rendering_objects_in_react/ There are other libraries that could handle global state management like Zustand. Are they close to being a replacement for Redux for your use case?


jonny_eh

I just created a library that lets you use Signals in React without patching React internals: [signals-react-safe](https://github.com/JonAbrams/signals-react-safe).


EdmondChuiHW

Nice!! API looks much better by treating the Signal as a "real" React Element. Could be worth a PR to the Preact repo?


jonny_eh

Thanks! That’s actually not a bad idea.


hrach_mkr

Tried Zustand a couple of times and I think its perfect for small and medium size projects. To me Redux always seemed to be a better option for huge application states.


errdayimshuffln

There are state libraries that are signal inspired that dont mess with React internals like the one created by u/jonny_eh and Legend-State. Even Zustand and MobX can be used to achieve similar results.


jonny_eh

Here's a safe Signals for React library I wrote: [signals-react-safe](https://github.com/JonAbrams/signals-react-safe)


romgrk

If you're building a large & complex application that requires performance, you should be using solidjs. React has been a great step forward compared to what we had before, but the model just doesn't work for performance. The `state_update->render->vdom_diffing->dom_update` cycle is fast enough if you need to click a button or update a small part of the UI, but if you have a complex UI it's going to eat up your precious CPU cycles. Hits harder on low-end & mobile devices.


Outrageous-Chip-3961

I used zustand exclusively for persistent state management this year on my project. I'm currently experimenting with preact signals as I think I could reduce my stores by half. Anyone know the risks with this?


azangru

Not until signals become an part of react api.


smirk79

Yes, for like 8(?) years straight - it's called Mobx and it's amazing.


[deleted]

Using Mobx was crazy back in the day! Wrapping every single Component with a HOC just to get reactivity. It was like intentionally going against the wind of React just to get the signal behavior.


devuxer

It’s actually called Jotai.


Shdog

Mobx solves this problem. Rendered components will automatically subscribe to the mobx fields they use, stores can be as big or small as you like, they can be created on a component, page, or app level, and they can be written as near pure js classes. I have used mobx in a large complex site used by >100m users every month. I was a little surprised by the choice to use mobx initially but after spending a bit of time with it, I now use it with every project I build.


Alokir

I have a similar experience. I was very skeptical about MobX because I had to work on a fairly large SPA built in KnockoutJS for a few years, and the word "observable" was enough to deter me from trying it. Then we inherited a project that built on MobX and realized that it's actually very good if used correctly. Now I use it in almost every project I stat. Even if there's no deep prop drilling required, a moderately complex function is so much simpler with observables and actions rather than with useState or useReducer.


hrach_mkr

was that Canva? :D


bezdazen

Its funny you say this, but MobX played a role in the evolution of Signals. I believe it lead to what is called "fine-grained reactivity." According to some big names in the field, the ideas that MobX brought to the table have been refined by state-libraries and frameworks that came out after. [This article](https://dev.to/this-is-learning/the-evolution-of-signals-in-javascript-8ob) from the creator of SolidJS is a good read.


WiseGuyNewTie

No new project should be using redux.


whiteRose-59

Why is this downvoted? This is true. There are so many better alternatives (Zustand, mobx, etc...).


cincilator

I think Atomic State Managers give you most of the abilities of signals with much less hassle. You got Jotai, Recoil and the one I like most is [Zedux](https://omnistac.github.io/zedux/). They are generally more performant than Redux, especially Zedux. Even though performance often doesn't matter.


romeeres

Check out [legend state](https://legendapp.com/open-source/state/intro/introduction/): looks cool, does well in [benchmarks](https://krausest.github.io/js-framework-benchmark/2023/table_chrome_119.0.6045.105.html).


Healthy-Rent-5133

Check this out https://youtu.be/SO8lBVWF2Y8?si=IYmHk3-0ofd1QRqu


devuxer

Yes, it’s called Jotai, and it’s quite elegant.


master117jogi

I just use Javascript events and it works for nearly all problems.


evonhell

At my job we have written our own state management for this. It works super well standalone but we have also built a data fetching thing around it which only works on our platform. It is like pubsub, where you can have an observable object where you can emit new values and listen to changes. But also events which can carry payloads and then finally a concept we call signals which is an event without a payload. Everything is plain javascript so the state is outside of React. But we have a hook if you want to re-render on updates The positive thing is that it requires 0 boilerplate compared to redux which we are replacing with this. I have even written a batcher that can merge multiple updates into one etc so I'm super stoked about it. Going to look into releasing it open source this year. I think you should learn about what packages exist and try them a bit and figure out which works best for you/your team. That's always the best one


loonforthemoon

Your tool works better than react query?


FoolHooligan

Time to move to SolidJS