Redux Alternative [closed] - javascript

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 2 years ago.
Improve this question
I have recently started learning React and I quickly encountered the problem of a bloated parent component full of functions and state. At first I looked at Flux and then I looked at Redux but both seemed like really overbearing solutions.
I am wondering why something like this is not done:
//EventPropagator.js
let EventPropagator = {
registerListener(listenerObject){
if (this.listeners == null)
this.listeners = []
this.listeners.push(listenerObject)
},
fireEvent(eventObject){
let listenerList = this.listeners.filter(function(listener){
return listener.eventType === eventObject.eventType
})
listenerList.forEach((listener) => {
listener.callback(eventObject.payload)
})
}
}
export default EventPropagator
To use: components simply registerListener and fireEvent:
//main.js
import EventPropagator from './events/EventPropagator'
EventPropagator.registerListener({
"eventType": "carry_coconut",
"callback": (payload) => {
// actually carry coconut
this.setState({"swallow_type": payload.swallow})
console.log(payload)
}
})
EventPropagator.fireEvent({
"eventType": "carry_coconut",
"payload": { "swallow": "african" }
})
This would allow a lot of decoupling and state could easily be passed around with this sort of event. What are the downsides to this approach?

You should try mobX
mobX is a state management library which took the advantage of decorators and succeeded in removing unwanted code. For example, there is no concept of reducers in mobx.
Hope this helps!

There is Reactn based in hooks.
It is orders of magnitude easier to use, compared to Redux.
Check https://www.npmjs.com/package/reactn and read Stover's blog.

Redux is a continuation of React's declarative programming Style. A simple way of mapping your application logic to components is to use something like Backbone.React.Component but using redux, will let you use all the tooling & middle-ware. Also have indefinite transitions in your apps makes debugging a lot easier. Now, I agree that you need a lot of wiring & boilerplate to get anyway.
If you want to use redux, you could look at something like redux-auto
Redux-auto: Redux made easy (with a plug and play approach)
Removing the boilerplate code in setting up a store & actions. why? This utility to allow you to get up and running with Rudux in a fraction of the time!
You can see now a redux-auto: helloworld project

If you want to take advantage of all the Redux benefits, use Redux.
If you only want to keep a var on sync between React components, use Duix.
I'm the Duix's creator. I've been using it for 1 year, and finally, I released it a few hours ago. Check the doc: https://www.npmjs.com/package/duix

You should try Hookstate. It gives the same simplest API for local, lifted, and global states. First class typescript. DevTools support. Extendable with plugins. Comprehensive documentation. It has got state usage tracking feature and smart re-rendering of only deeply nested affected components. This makes it the fastest state management solution for large frequently changing states. Disclaimer: I am maintainer of the project.

What is needed is an event driven system so a child component can speak to its sibling but this does not mean that data should be passed as the events payload. That would lead to a system of no governance and a nightmare for a project where multiple developers are working on it.
So long as you follow the flux-like architecture pattern (google it) then you actually can do this successfully with just javascript and Javascript objects to hold the data along with the event system.
Data should be treated as being one of three different states. It's either
original data pulled from the server
transformed data (transformed from the original)
Store data. That which acts as the model which the UI is bound to
If you write a javascript library to handle the movement of data between the three states and handle the transforms you can use the event system to to fire a "store changed" event that components can listen to and self-rerender.

https://github.com/deepakpatil84/pure-data
Note: i am the author of this

Using your EventPropagator solves the problem of communication, but does not handle data integrity. For example, if there are more than 2 components listening to same event, and using that event's payload to update their own states. The more components listen to same events, the more complex it is to make sure that all those components have same data in their own states.
Secondly, Flux/Redux provides uni-directional data flow. A simple example could be about 2 components A & B, consuming same data X from external source (API or storage). User can interact with either of them to get latest X data. Now if user asks B to update X, we have 2 solutions with your EventPropagator:
B will update X itself, and fire an event to inform A about the update to let A re-rendered. Same goes for A if user asks A to update X. This is bi-directional data flow.
B will fire an event to A asking to update X, and await A to fire an event back to get updated X. If user asks A to update, A will do it itself and inform B. This is uni-directional data flow.
Once your number of components goes large and communication is not limited between only A & B, you might need to stick with only one of those 2 above solution to avoid your app's logic going wild. Flux/Redux chooses the second, and we are happy with that.
If you really don't think you need another library for data control, you should look at the newest feature of React: Context. It provides most essential features that a data control library can have, and it's React only. Noted that you have to update your project's React version to 16.3 to use this feature.

Another modest multi-store alternative is react-scopes
Here are some features:
Simple decorators syntax,
Allow defining independent store logic directly in Components
Easily connect stores through the Components tree
Allow templating complex / async data process
SSR with async data
etc

I wrote Reducs. It's only 25 lines of code, it doesn't require boilerplate, and... did I mention that it's only 25 lines of code?
I am using it for a big project, and it's holding up very well. There is a live example that uses lit-html and Reducs.

I faced similar issues, with lot of switch, case, etc...
I create for myself something as alternative, you could take a look:
https://www.npmjs.com/package/micro-reducers

Take a look on JetState for state management with RxJS. I wrote this for my Angular projects and later adapted it for using with React's hooks.

PullState I really want this underdog to shine. Tried other similar ones which promised quick and no-boilerplate-ness, none came close to the ease of use of PullState. I just read the first page of the documentation and implemented it in one of my pages and it just worked. It is easy to understand if you already using functional components in react.

Related

Question about Redux async operations with Thunk

I just recently got introduced to Redux and decided to learn how to implement it. At the moment I'm refactoring some of my previous studying-projects and implementing the global state logic provided by the tool.
The thing is, I've recently stumbled upon the thunk middleware for async actions and got curious about something that's probably a simple concept misunderstanding but that I just can't get over.
So, why would I dispatch an async action? I just can't see the benefits of doing that way instead of waiting for the execution of whatever I'm doing and just then dispatch the action carrying the data I want.
Using a simple fetch call as an example, why would I not do the following:
->await fetch data
->dispatch fetched data
And instead do this:
->dispatch action
->await dispatch action
There's probably some use cases that I don't know of because for me, a beginner, sounds like extra code for something that maybe didn't require it? Idk.
Could someone help me? =)
Yep, as you found, that's Dan Abramov's original explanation of why something like the thunk middleware exists.
I recently wrote a new Redux docs page on Writing Logic with Thunks, which goes into more detail on the purpose behind thunks and how to use them correctly. I'll quote from the "Why Use Thunks?" section:
Thunks allow us to write additional Redux-related logic separate from a UI layer. This logic can include side effects, such as async requests or generating random values, as well as logic that requires dispatching multiple actions or access to the Redux store state.
Redux reducers must not contain side effects, but real applications require logic that has side effects. Some of that may live inside components, but some may need to live outside the UI layer. Thunks (and other Redux middleware) give us a place to put those side effects.
It's common to have logic directly in components, such as making an async request in a click handler or a useEffect hook and then processing the results. However, it's often necessary to move as much of that logic as possible outside the UI layer. This may be done to improve testability of the logic, to keep the UI layer as thin and "presentational" as possible, or to improve code reuse and sharing.
In a sense, a thunk is a loophole where you can write any code that needs to interact with the Redux store, ahead of time, without needing to know which Redux store will be used. This keeps the logic from being bound to any specific Redux store instance and keeps it reusable.
The Redux FAQ entry on "why do we use middleware for side effects?" links to additional information on this topic.

React-Redux How to improve performance?

I am using the react-redux for one of my app, The design is quite difficult and performance required is very high. its actually wyswyg builder.
We have been using the react from last 2 months, Then we moved to the react-redux for the separation of code and improve maitainance, code readability and the parent-child approach headache ofc.
So, I have an array which has quite complex structure
This is how my state look a like:
const initialState = {
builder:{},
CurrentElementName:"",
CurrentSlideName:"",
.......
}
As redux recommend to have less data in particular object as possible, I have another 8-9 reducer which are divided from the main state.
My problem: builder object is very complex which has almost 3-4 levels down, objects and arrays, this all are managed runtime.
So, on the componentdidmount my application will call the server get the data and fill the builder:{}
builder:{
slidedata:[{index:0,controName:'button',....},{index:0,controName:'slide',....}],
currentSlideName:'slide1',
currentElementName:'button1'
}
This builder object is quite complex and depends on the user actions like drag and drop, changing the property, changing events, changing position this builder object is being changed by the reducer
let clonedState= JSON.parse(JSON.stringify(state));
//doing other operations
Every time some thing changes this object needs to perform certain complex operations, for ex, adding the new slide will do certain operations and add the slide to the current array called slidedata.
What is the best practice to fast this things up? am I doing something wrong?
I am not sure what is the wrong in this code, and as redux recommend I can not use the flat structure for this particular array as its managed run-time.
I am sure that component has the data which the component wants.
Is there any way to handle the big data? This iterations and changing the state is killing my performance.
Based on my current experience with React-Redux framework, Re-select and ImmutableJS make a perfect combination for your requirement.
Re-Select uses memoization technique on Javascript objects and have list of API's specifically dealing with these kind of large set of Javascript objects thus improving performance. Read the docs.
Note: One should wisely read the documentation before using this setup to churn the best of these tools.
You can either create your own boilerplate code using above libraries or use the one which i am currently using in my project.
https://www.reactboilerplate.com/
This boilerplate is specifically designed for performance. You can customize it based on your needs.
Hope this helps!

Redux architecture for text editor: dealing with coupled state

I'm building an app with React/Redux that is in some ways similar to a text editor. It's not a text editor exactly, but it's the same general paradigm. There is a cursor for placing new items. Items can be added, selected, deleted, etc.
I'm struggling with the best way to structure my reducers in a way that is in keeping with the spirit of redux. I have separate state slices representing the selection state, the text itself, the cursor state, and other settings. I think the "redux" approach would be to have reducers for each of these state slices, independently mutating state in response to an action.
However, in a text editor these state slices are a lot more coupled than at first glance. When you press a key, sometimes a letter will be added at the location of the cursor, and the cursor will move forward. If text is selected, however, the selected text will be deleted first. If you are in "insert" mode, text to the right will be "consumed". Or maybe a modifier key was down, and text isn't added at all.
In other words, the different state slices are very coupled and what happens in one depends on the current state of the others.
I've read the "Beyond Combine Reducers" section in the Redux manual and know how to share state between slice reducers, but this seems inelegant if the end result is passing the entire state to every slice reducer. The other thing I don't like about his approach is that each reducer would have to look at the overall state and independently come to the same conclusion about what its correct response to a particular action should be. Is that what I should be doing or I should be structuring my state differently somehow?
The alternative of one centralized reducer telling the cursor, the selection state, the content, etc. how to mutate is easier conceptually but doesn't seem to scale well.
I've also read that many times coupled state is a sign that your state isn't minimal and that you should be restructuring and using memoized selectors. However that doesn't seem to be the case here. The position of the cursor is not derivable from the text, nor is the selection state.
Lastly, I've also considered Thunk middleware as this is something that I've seen suggested for handling multiple/more complex actions. I'm hesitant because it seems like it is more meant for asynchronous dispatch and this is not that.
I'd like to understand the correct approach for designing this type of app that is most in keeping with the "redux" design pattern and understand any tradeoffs there might be if there are multiple ways forward.
I wrote that "Structuring Reducers" doc section, so nice to see that people are at least reading it and finding it useful :)
You're right that the idiomatic intended approach for Redux reducer logic is small reducer functions, organized by slice of state, independently responding to the same actions. However, that's not a fixed requirement, and there are definitely times when it makes more sense to consolidate some of the logic into one place.
It's a bit hard to give absolute specific advice without seeing what your state structure is and exactly what problems you're trying to solve, but overall, you should feel free to structure your state and your reducer logic in whatever way makes the most sense for your application. If it works better to have some of that logic in a more centralized reducer function that updates several nested pieces of state at once, go for it!
As a couple other observations:
Per the Redux FAQ question on "sharing state across reducers", one approach is to put more information into the dispatched action. For example, rather than dispatching {type : "KEYSTROKE", key : "A"}, you could dispatch {type : "KEYSTROKE", key : "A", cursorPos : 12345, ctrl : true, alt : false}.
Also, while thunks are a good place for basic async logic, they are also useful for complex synchronous logic as well, including inspecting the current app state. I have a gist that demonstrates some common thunk use cases.
Lemme toss out a couple more resources that may be of general assistance to you:
My React/Redux links list has a section linking to articles on writing reducers
My "Practical Redux" tutorial series demonstrates a few variations on reducer structures, including the post Practical Redux, Part 7: Form Change Handling, Data Editing, and Feature Reducers.
(As a side note, I'm also currently working on a blog post that will discuss what actual technical limitations Redux requires and why, vs how you are "intended" to use Redux, vs how it's possible to use Redux. Will take me a while to finish it, but keep an eye on my blog if you're interested.)
Finally, if you'd like to discuss things further, the Reactiflux chat channels on Discord are a great place to hang out, ask questions, and learn. The invite link is at https://www.reactiflux.com . Please feel free to drop by there and ask questions - I'm usually on there evenings US time, but there's always a bunch of people hanging out happy to discuss things.
Seems you are taking a huge task; probably you already know that, but creating a text editor from scratch is not an easy task.
Did you evaluated using an existing software?
Recently I used with success the super powerful Codemirror and integrated it with a React.js application. Codemirror already manage the concept of state of the document in a great way.
That means:
Codemirror instance fully manage the editor (AKA: the document)
React environment is attached to the document through callbacks and events.
If Codemirror doesn't fit your needs, take a look at it's code and internals description.

Aurelia + Redux performance

I use Aurelia on a daily basis. Recently, I have been looking into using Redux (i.e. I built a couple of small trial apps using Aurelia+Redux) and have been really impressed (my development workflow and clarity of reasoning about my application is greatly improved). I have decided that I would like to start working it in to real-world applications.
With that said, I have a concern regarding performance (I have looked around at posts about performance but haven't seen my issue address directly). I think this question is not specific to Aurelia, more a question about Redux and using it with non-react libraries.
Let me preface my question with my understanding of Redux (perhaps my question is really arising from a flawed understanding?). Essentially, the way I understand Redux is that there is a store (a javascript object) and a reducing function. Now, the reducing function may be defined as a tree of functions (each responsible for modifying a specific branch of the overall store), however, in reality, Redux receives a single reducing function (it has no way of knowing how many functions were composed to create this single function).
The way I am using Redux is like so (just an example):
#inject(Store)
export class TodosListCustomElement {
constructor(store) {
this.store = store;
}
activate() {
this.update();
this.unsubcribe = this.store.subscribe(this.update.bind(this));
}
deactivate() {
this.unsubcribe();
}
update() {
const newState = this.store.getState();
this.todos = newState.todos;
}
toggleCompleted(index) {
this.store.dispatch({
type: UPDATE_TODO,
payload: {
index,
values: {
isCompleted: !this.todos[index].isCompleted
}
}
});
}
}
Essentially, each component down the component tree, subscribes itself to store changes and refreshes the data it needs from the store.
My concern is that there seems to be a lot happening on each published action. For example, say I have a large application with a similarly large store and reducer tree. Suppose there is some throttled textbox that dispatches changes to a single text field (in one item of a list) in the store every 250 ms. That would mean that as a user types, the entire reducer function is executed every 250ms (which could mean executing quite a large number of its descendant reducers) as well as all the subscribing functions are executed as well. Basically, it seems like there is a lot of overhead to change even the smallest part of the store.
Contrast this with a standard binding (in Aurelia) where there is just a single bound function (mutation observer) that needs to execute every 250ms to update the model...
Since I am new to Redux, I guess there is a good chance that I am naively misunderstanding something etc. I apologize in advance and hope to be corrected/put on the right track (because my limited experience using Redux has been very enjoyable).
Thanks in advance
You're actually describing the situation pretty well, on multiple levels.
First, the React-Redux bindings do a lot of work to ensure that connected components only actually re-render when some of the data relevant to a given component has changed. This is done by having a connected component supply a function called mapStateToProps, which extracts the data that component wants from the store state. The wrapper components generated by connect will re-run their mapState functions after each dispatch, and do shallow comparisons between the latest returned values and the previous returned values to see if the data has changed. That cuts down on the amount of actual UI updates that need to be done.
There's also tradeoffs involved in how you handle connected forms. Yes, dispatching an action for every single keystroke is likely to be inefficient overall. I personally use a React form wrapper component that buffers those text input changes locally, and only dispatches a debounced Redux action after the user is done typing.
The React-Redux bindings were recently rewritten, and are now primarily based on memoized selector functions rather than having most of the logic inside of React components. I don't know how the Aurelia bindings are put together, but I suspect that they could probably leverage a lot of the work that's been done to optimize the React bindings.
You may be interested in some of the articles I have on Redux-related performance. See the Redux FAQ question at http://redux.js.org/docs/faq/Performance.html#performance-scaling , as well as the articles in my React/Redux links list at https://github.com/markerikson/react-redux-links/blob/master/react-performance.md#redux-performance .

Backbonejs, Event Aggregation and Instantiating Views [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
tl;dr
To what extent is the Event Aggregator pattern duplicating what Backbone.Router already does? Wouldn't it be better if Views didn't communicate with each other, even with events?
The trouble
I'm having a conceptual problem with the use of an Event Aggregrator in a Backbone application. My very basic implementation is derived from Derick Bailey's post about it.. I'm using it in Requirejs and I just define a module that extends Backbone.Events and require it in the modules where I need it.
A bit of background: The problem I was trying to solve in the first place was how best to handle transitions between views in my app. Especially automated transitions. It was clear from my reading that two obvious methods were discouraged:
Manually firing a navigation callback on the router with something likerouter.navigate("login", { trigger: true })
Manipulating the browser window.location.replace("/#login") and thus triggering the relevant routing callback.
As far as I can tell, the main objection to both these methods is a loss of the proper separation of concerns. As I can certainly see the value in avoiding Views having to know too much about each other, I looked about for a better way and found the Event Aggregator.
The problem I'm facing with the Event Aggregator, though, is made quite obvious from Derick Bailey's example on his blog post. The views that respond to the events are already instantiated. Any view that is not already instantiated will naturally not respond to any events. So if, for example, I want an event to instantiate a new View as a result of some logic, I either:
Instantiate a new instance inside the current View. In this case I lose most of the advantage of the approach, because now my Views need to know about each other again.
OR
Create some kind of central event-handler that instantiates new Views based on specific events. Which sounds a lot like the original Backbone Router to me. It seems like I could just separate the logic for each Router callback into various Controllers and I'd have the same clarity.
My second problem is perhaps more general. I feel like the Event Aggregator encourages active inter-communication between Views: admittedly in a decoupled way. Ideally though I'd like to keep that to a minimum. Really I want my user to perform fairly self-contained actions within a defined area and then transition to a new area. Am I being naive, in hoping to sustain that?
I feel like I must be missing something obvious, but right now it feels like the Event Aggregator solves the problem of inter-View communication (which I'm not sure I want), but ends up replicating the Router with regard to View management. The problem I have with that is that I'll have two Event systems acting in parallel.
What I'm really looking for is a sensible, reasonably lightweight pattern for handling the instantiation of Views using the Event Aggregator. I know I could look into Marionette, but I'd prefer to understand this on my own terms first, before diving into another Framework.
Oh backbone, confusing as ever. Everyone still has differing opinions on how a good application should work.
So here's my opinion.
For your first problem, have you considered just using an anchor tag in one of your templates?
Login
For your second problem, I'd take a page from other frameworks. Before our company switched away from backbone/marionette we tried to adopt the flux (redux) architecture on top of backbone. It has worked out pretty well for some applications that stayed on backbone.
Adopting that architecture just meant defining some best practices. I think the following rules could work for you:
The event aggregator will be the only thing that can fire route changes directly.
At minimum 2 levels of views (or objects) are needed for any page.
The top most views is called a "smart" or "highly coupled" view (or object). It will allow you to hook into the event aggregator and then pass data or callbacks downward. They can represent layouts or can be mostly devoid of style and just transform event aggregator callbacks to something the generic views can work with.
The 2nd level and below should be designed in a decoupled way. We can call them "generic" views, and they can accept handlers as arguments. This is how they communicates with the outside world.
This means, views have APIs and smart views need to adhere to those APIs.
Quick Example:
function init() {
// this level is highly coupled, and knows about the events
// that will occur
var aggregator = new Backbone.Events();
aggregator.on('gotoLogin', function() {
router.navigate("login", { trigger: true });
})
function gotoLogin() {
aggregator.trigger('gotoLogin');
}
// the Todo class is generic, and defines an API that expects
// a gotoLogin callback
new Todo({
el: '.js-todo',
gotoLogin: gotoLogin,
});
// the Header class is generic, and it also expects
// some way to navigate to the login screen.
new Header({
el: '.js-header',
gotoLogin: gotoLogin,
});
}
If you are building your application as some sort of single page app. This will cause you to nest views, which isn't the end of the world, but it does become tricky with backbone, but is still doable. In fact, you may be able to automate creation of child views (see marionette). I bring this up because it seems vaguely related to the original question around de-coupling. I think the nested view problem in backbone is particularly problematic.
I believe people over-emphasize reusable code and decoupling. Honestly, there needs to be some amount of coupling. Finding an acceptable level is difficult. Defining it when everyone using backbone has differing thoughts on it, is very difficult. My recommendation is that you and your team should figure out a system that works well for you in backbone land and stick to it otherwise chaos will surely ensue.

Categories