In Flux every action should be handled by the dispatcher.
What about an action that doesn't alter the view or the markup, such as "scroll this element into view"? What is the "Flux-way" of handling such a scenario? To by-pass the dispatcher? Or to handle it in the dispatcher without involving the stores or the components?
Flux is really more about application state management, and is not at all about the details of what components are rendered in the view. That's the domain of React. Flux simply assumes you have some kind of reactive view layer -- usually that's React.
Application state is not the same as component state. Application state is something that needs to be known in multiple components. For component state, React's this.state is perfectly adequate. An input component is a good example of something that might need this.
So in your case, if only one component needs to know the scroll position, there may not be a good case for moving that state to a Flux Store. But as soon as that needs to be known in multiple components -- especially components in different branches of the tree -- you probably want that state being managed in a Store.
The other issue your question raises is the role of Flux Actions. A Flux application always uses Actions as the origin of the data flow. There are a lot of good reasons for doing this: stable application state, keeping the app resilient to new features, keeping it easy to reason about, undo history, reconstitution of application state, stateless view components, etc.
Occasionally people want to write as little code as possible and they use a callback passed between components to change this.state in the parent component instead of dispatching a new action to go through the Flux data flow. I find this to be mixing the view and state management layers of an application, and while expedient, this can lead to a lot of headache. It isn't very flexible in the long run, because now the state is coupled to these few components. Building up a Flux data flow from the start is much simpler in the long run, and much more resilient to new features. That said, it also requires more investment in code up front.
If your app doesn't need to know about scrolling (seems rare that it would), there's no need to fire an action. Since Flux is really there to handle data flow (and subsequent changes based on that data flow), it doesn't need to know about every action that occurs.
Related
I am working on investigation of one front-end application of medium complexity. At this moment it is written in pure javascript, it has a lot of different event-based messages connecting few main parts of this application.
We decided that we need to implement some kind of state container for this application in scope of further refactoring. Previously I had some experience with redux and ngrx store (which actually follows the same principles).
Redux is an option for us, but one of the developers proposed using a state-machine based library, in particular the xstate library.
I've never worked with xstate, so I found it interesting and started reading documentation and looking at different examples. Looked promising and powerful, but at some point I understood that I don't see any significant difference between it and redux.
I spent hours trying to find an answer, or any other information comparing xstate and redux. I didn't find any clear information, except some articles like "get from redux to a state machine", or links to libraries focused on using redux and xstate together (quite weird).
If someone can describe the difference or tell me when developers should choose xstate - you are welcome to.
I created XState, but I'm not going to tell you whether to use one over the other; that depends on your team. Instead, I'll try to highlight some key differences.
Redux
XState
essentially a state container where events (called actions in Redux) are sent to a reducer which update state
also a state container, but separates finite state (e.g., "loading", "success") from "infinite state", or context (e.g., items: [...])
does not dictate how you define your reducers - they are plain functions that return the next state given the current state and event (action)
a "reducer with rules" - you define legal transitions between finite states due to events, and also which actions should be executed in a transition (or on entry/exit from a state)
does not have a built-in way to handle side-effects; there are many community options, like redux-thunk, redux-saga, etc.
makes actions (side-effects) declarative and explicit - they are part of the State object that is returned on each transition (current state + event)
currently has no way to visualize transitions between states, since it does not discern between finite and infinite state
has a visualizer: https://statecharts.github.io/xstate-viz which is feasible due to the declarative nature
the implicit logic/behavior represented in reducers can't be serialized declaratively (e.g., in JSON)
machine definitions, which represent logic/behavior, can be serialized to JSON, and read from JSON; this makes behavior very portable and configurable by external tools
not strictly a state machine
adheres strictly to the W3C SCXML specification: https://www.w3.org/TR/scxml/
relies on the developer to manually prevent impossible states
uses statecharts to naturally define boundaries for handling events, which prevents impossible states and can be statically analyzed
encourages the use of a single, "global" atomic store
encourages the use of an Actor-model-like approach, where there can be many hierarchical statechart/"service" instances that communicate with each other
I will add more key differences to the docs this week.
State machine does not tell (force) you to have Unidirectional data flow. It has nothing to do with data flow. It is more about constraining state changes and about state transitions. So, generally only some parts of the application would be designed with State machines, only and only if you need to constraint/forbid some state changes and you are interested in transitions.
Beware that with state machines, if for some reason (external API dependency etc...), there is chance that app might get locked in a state where it can't transition to another state because of constraints, you have to solve it.
But if you are only interested in last app state itself, instead of state transitions, and state constraints do not matter, then you better be not using state machine and directly be updating state itself (you can still wrap state in a Singleton class update through Action classes).
On the other hand, Redux is Unidirectional architecture framework. Unidirectional architectures enforce you to have single direction of data flow. In Redux, it starts with User->View->(Action)->Store->Reducer->(Middleware)->Store->(State)->View. Like State Machines, you can trigger side effects with Middlewares in Redux. You can constraint/forbid State transitions, if you want. Different from State Machine, Redux forces unidirectional data flow, pure! reducer functions, immutable state objects, single observable app state.
few of my points below.
The UI-state and business/backend state are coupled together in redux. Because of this every update on the ui or business state creates a data update in the redux store.
Xstate decouples UI state and backend state.
In redux all nodes are present inside a root node. Xstate decentralises and distributes data inside independent Machines.
Application can only transition between the states defined already. So any error or bug can be fixed in the Machine itself.
Internal states are managed by the Machine itself in Xstate. Redux represents new states as flags.
Renderer agonistic - keeping as much of the state hoisted into Machines, and if we need, we can switch rendering frameworks relatively easy (eg from react to vue).
Contexts provides concrete class to present a single interface to the outside world.
I'm quite new to React, and I'm making a single page application with React.
So far, I've build the application with components and child components, having their own local state, however the child components doesn't really interact with one another, which is what I want them to, basically, with the least amount of boiler plate code...
The problem I'm facing, is that a change in some child component, should be able to update the state of another child component, somewhere else in the component tree.
A selection in one child component should also be able to trigger a function in another component updating it with data and so on.
I've considered having just one global application state, that all components can call and update when something in them changes, and this one application state will then update other components in the tree. Kinda like having a single "controller" with it's own state, that all components "views" can call, and which updates the states of other components as needed. (I'm used to WPF and MVC style of GUI programming).
What I've considered:
One could try to implement this with callback functions defined in the top of the hierarchy, to be sent down through the hierarchy and called from a child component when it changes.
This method however results in a LOT of boilerplate code that just passes functions to their child components. It feels wrong and hard to maintain...
To avoid all this passing around and boilerplate code, I've tried using a React Context, however this is not working as well as I hoped. I can only access the context from within the render function and from lifecycle functions, and sadly I often get complicated errors that are hard to understand. It seems like I'm exploiting React Context to do something you shouldn't use it for...
I've considered using a singleton pattern in JavaScript, however then that singleton needs to have a reference to the root component, and query for the component it needs to change... This seems like kind of a hack, and may not be that pretty, but idk.
I'm considering trying out React Redux however it seems to work in many ways similar to React Context (I'll be honest, I haven't read much into it yet).
What I need:
I need to ask someone with greater React experience than me: How do you keep a global application state, and update child components based on changes to the global application state? Also: Am I thinking about this all wrong? Am I trying to do something in a non-react way, failing to see how I should do it in React?
You can happily go with Redux or MobX, they're fine.
I suggest Taming The State from Robin Wieruch: https://roadtoreact.com/course-details?courseId=TAMING_THE_STATE
There are the book and the course. He shows different ways of handling React state.
Redux was created specifically for the problem yo stated.
Reacts follows a top-down down-top unidirectional flow in essence. Context API is useful in simple use cases but would fail horribly in a large scale application where you'd be creating consumers everywhere.
I'd suggest investing some time in Redux so that will save your precious time in long run.
There's a reason all big three frameworks require a state management library to be useful for large scale complex apps. (Angular has NgRx and Vue has Vuex).
So Basically, I came across many articles where they are referring to manage state via flux or redux.
I wanted to know that how about UI component having its own state? Is it good practice to let redux manage the Api call and success toast messages etc. but UI components should have their own local state?
Kindly someone elaborate what is the best practice in industry?
Though the question calls for opinion, I am going to leave my answer. There is no standard best practice regarding this. It boils down to convenience and ground rules of your team, if there are more than one people writing the code.
I use Redux quite a lot. However, I won't refrain from using local state in components.
Form handling like input onChange handlers require local state. It is not performant to use global state for onChange handlers.
Reusable component uses local state. Again, it boils down to whether the reusability is a technical reusability or business reusability. If you are developing a custom scrollbar component, use local state. However, if you are using a comment form which is used everywhere in your application, use global state.
I prefer to have most of the stuff in global state. I use redux thunk as well. In redux thunk, it is possible to access global state within the thunk function. This is quite useful as it avoids the reliance for props / context being passed all around.
I do keep some simple things in local state -- for example, show / hide some stuff. I don't mind waiting for promises to resolve before hiding some stuff using local state.
Overall, the decision to use global state vs local state is primarily based on convenience. There are no standard rules other than what you and your team are comfortable with.
React is a way to declaratively deal with UI. There are some rules of the framework like state, props, context. It is left upto the developer to make the UI declarative and performant based on these primitives. How, a developer does it does not matter as long as the code is maintainable and understood by others.
After asking many professionals and industry developers, I came to know that managing state through redux depends on your application scope.
but more importantly, If I am working on enterprise Application then the application state must be managed through redux.
Now the question is what should be kept in our redux store. well, you can store almost anything in redux store but better to manage the local state of a component as well. for instance, opening a component Boolean should be managed in local state or any string or header name etc.
Good question! The answer is usually "it depends", but there are clear cases when you'd probably prefer to use one over the other.
Use Redux for storing state relevant to the application. E.g. the current page/panel that should be shown. As you mentioned, showing a notification/message - is something that'd make sense to store in redux state, as the alternative would be passing state all over the place, e.g. an error prop bubbling up to your root component which renders the toast message. Using thunk is also a good idea when you're fetching/manipulating data relevant to the whole app, e.g. a list of things that appear in several places.
Use component state for storing state only relevant to the component. That is, if you're filling in a form, it makes sense to store the value of text inputs, checkboxes etc. in your component state (perhaps in conjunction with container and presentational components) as the values at this point aren't relevant to the rest of the application.
I have often heard questions that ' Why one should use redux whether there is also a State in the ReactJs. Which extra facilities redux does provide to the developer ? '
For small applications when there aren't a lot of components, you can do without redux. But in large applications, it becomes pretty complicated/tedious to chain props through components especially if one that is deep 6 levels needs it.
This is a great article that explains it
https://blog.logrocket.com/why-use-redux-reasons-with-clear-examples-d21bffd5835
The Redux docs page about organizing state (here), list out a few reasons one might lean to using Redux store over component state. However, they do clearly state that "using local component state is fine" and that, in the end, the developer should find the proper balance for the work at hand.
Some common rules of thumb for determining what kind of data should be put into Redux:
Do other parts of the application care about this data?
Do you need to be able to create further derived data based on this original data?
Is the same data being used to drive multiple components?
Is there value to you in being able to restore this state to a given point in time (ie, time travel debugging)?
Do you want to cache the data (ie, use what's in state if it's already there instead of re-requesting it)?
Redux is required when your application is big with many components. Redux works as global meaning if you set value in one component you can get that value across components. This is the primary advantage with state management Library.
If your application is small with 10 to 20 components then we don’t need redux. We can pass down state to child components as props but when application grows big you will have so many components and it’s very difficult to play with component level state and you won’t have control of the flow and you can’t track of values between components
So redux is very useful in such cases.
I have been using vanilla React for a while, and have now decided to take a closer look at Redux for a new project I am doing.
At first I got the impression that all user activity should result in actions, with one of the main reasons being that you would be able to reconstruct any application state by just playing back the appropriate actions.
The problem with this, however, is that you put a lot of stuff in the store that in reality does not feel like application state. Stuff like "If I focus on this input, the label turns green" does not seem like state fitted for being represented in the application state of an application that is potentially composed by hundreds of components. These things make total sense with the typical todo-tutorial, but it can be difficult to see how it will turn out in a more complex scenario.
Then I read some more, and found that the general opinion, backed by creator Dan Abramov, is that you should usually combine local component state with the application state (store). "Whatever seems least awkward" seemed to be the rule of thumb for where to store state.
On one hand this makes total sense: The things that are really application state, and are relevant for multiple components should be in the store, while the strictly presentational details that only concerns one single component should be handled using normal react state. On the other hand this approach confuses me a bit, because of what I wrote in the beginning: Isn't a big part of the point with redux that you avoid having the state distributed among the components, and that you are able to recreate state by just storing the actions?
I hope someone can shed some light on this concern, because it has been bothering me, and it is something I think I should get a solid opinion about before trying to build something complex with redux.
What state you put where is entirely up to you. Sometimes it may make sense to put everything in Redux, sometimes it may make sense to keep stuff in a component. I recently saw some good rules-of-thumb:
Do other parts of the application care about that data?
Do you need to be able to derive further data from that data?
Is the same data being used to drive multiple components/features?
Is there value to you, to being able to restore the state to a given point in time (ie: time travel / debugging)?
Do you want to cache the data, ie: reload it from state if it's already there instead of requesting it again?
(Credit to https://www.reddit.com/r/reactjs/comments/4w04to/when_using_redux_should_all_asynchronous_actions/d63u4o8 for that list.)
Also see the Redux FAQ on this topic: http://redux.js.org/docs/FAQ.html#organizing-state-only-redux-state .