I'm working on an enterprise application which is huge on forms, there are pages and pages full of forms. Normally when it's just form, we could simply use a library like formik or react-hook-forms, but what I see time and again is when something changes, there's a business requirement to do something, which means I'm mutating form values programmatically.
We are currently using useEffect and put all those business logic side effects on components, but then it feels like I'm mixing view with business logic.
My instinct however is to use redux, and use redux-saga to manage all the side effects and complexity this way my UI is pure and is easy to write tests for. And redux-saga handles the business logic and side effect which is where they should belong anyway IMO, I want to know what the community is doing in this case.
My case, forms aren't as simple as displaying forms, and on submit, handle data, we also need to handle when something changes, we have some business logic and sometimes we actually update other values.
For things like this input is disabled when this checkbox is disabled it doesn't need redux, what about the rest? What are you guys doing?
We've integrated Redux in our project just because everyone is always talking about Redux in terms on ReactJS and we've figured out that it's a bit overhead and now complicates our code a LOT (we're using redux-observable for side effects).
Just ask yourself a single questions -
Are we going to share state between forms/pages/sections of the app?
If every form is separate and doesn't have anything to do with other parts of your application, so you don't need any kind of global state, Redux is overhead. You might want to consider structuring your app a bit better, move side-effects in your own hooks and just fully decouple your presentation from business logic - code being in useEffect, which happens to be in your component doesn't necessarily mean that it's part of UI logic, because you could easily move it in some kind of wrapper/service or later on to some kind of side-effect library (like redux-saga, redux-observable or something else).
Overall advice - don't overthink it and make it complicated, just try separating application concerns in simplest possible way and then along the road you'll start noticing what needs refactoring, code duplication which can be reused and whether or not you should introduce some kind of library that you can benefit from.
I worked on a very similar project with forms constantly resulting in side effects (fetch backend for input validation or autocomplete lists, dynamically change fields according to other field values etc.).
I used formik with the useField() hook, which allows you to read/write any field value/error anywhere inside the <Formik> tree.
Given this convenience, I wrapped the view components with logic components where the side effects are done in the logic component and just returns a view component to render. Both hooked into the fields with useField() but you might really take it to a more functional approach by passing the values/callbacks from the logic component to the view via props. This way you can easily swap out the view values with a different logic (creating a new form and editing an existing form both share the same view but use different logics).
We made a decision based on different aspects, because redux is too verbose, we didn't want to use it, but that's not how engineers choose tech.
We decided to give weights to each points:
Performance (5)
Duplication of states (5)
Ease of handling side effects (separation of concerns) (10)
Learning Curve (3)
Unit testing easeness (7)
Debugging (Dev Experience) (5)
Verbosity (less verbose is better) (5)
When we evaluated these, redux with saga came out top, sure formik has it's strength, but our whole App is just forms, and those forms aren't as simple as rendering and doing some minor side effects, it's huge form and side effects happen in such a complex ways, that just being able to track down issues using devtools is already huge.
Another thing is having a redux-saga layer helped, anyway, that's how we made the decision, but 99.9% of forms should continue using formik, but unfortunately we're at that 0.1% where redux scales with number of developers (5000+ dev in company, 50+ actively contributing to this project), and redux having devtools and ability to separate side effects, exploring data etc just made more sense.
Please choose your own when you need it.
https://github.com/reduxjs/redux/issues/1287#issuecomment-175351978 Dan says use redux if it matters globally OR is mutated in complex ways our form is mutated in such a complex ways that it's very difficult to maintain code in future, formik made it easy to write code, but redux makes it easy to debug and maintain. (for us)
I see no reason to use either redux and redux-sagas here.
You could simply use context API instead of redux. As far as redux-sagas is concerned. You could simply separate your API into different functions and keep it separately from your views.
redux-sagas are not worth it in my opinion. It is bloated and requires a learning curve about the API for the next developer. You want to keep the enterprise applications as simple as possible to keep in mind that, the next developer doesn't need to learn a bunch of APIs to edit your form. It's just a bunch of forms. Keep it simple.
Use formik and store all your state values in the localStorage on every handlePress so that it persists on refresh and on pressing the back button. Written a lot of complicated forms even with payments. Formik is literally everything you need.
And that would definitely be it. I would argue you could get away with using just formik instead of context API.
TLDR :-
It's just a bunch of forms.
It's just a bunch of API calls.
No need to overcomplicate things.
Use the native API like context or a form library.
Separate your API into an API folder.
And more importantly, store all your form values
in a cookie, if you want it to expire,
or in sessionStorage if you don't want to share data across tabs.
or just localStorage
Related
I have seen it is becoming mandatory to use state pattern i.e mobx or rudux etc for building any react application. I am concerned that how much it is necessary to use these patterns. like if i have an application and have some pages in it each one is populating data with calling some restfull. So we can have handle it by adding some of optimization techniques like useEffect, usememo and usecalback and obviously custom hooks etc. Shouldn't it must be cleared before starting development application that how much we want to track changes in applications and how much global state we want to use. it we want only one global state ie auth status. we can use simple context and doing all with having simple techniques. So that our application become less dependent upon these libraries. If it is not like that which are the requirement that must be cleared before starting an application to decide whether to use state pattern or going with simpler version of react
It's not mandatory. In fact, my startup's codebase doesn't use any state management library. Just useState and for a few special cases we rely on useContext. React even offers useReducer (which is a simplified Redux).
I used Redux for a project and I hated it. If you're going to use it, follow the rules. Redux should be side effect free and immutable. When needing async data, you often have to use complicated middleware and other libraries (e.g. Redux-Sagas).
The good thing is that you can use a state management library for a part of your app. Maybe even another state management library for a different part.
In some cases, it might be useful to use a state management pattern. Certainly when it allows you to make some logic more understandable, readable or testable.
My take away: Always try to keep it simple
I am planning to build a large React application which might contain hundreds of components. But not sure what state management system to use between Redux and Context API.
Context API is in-built in React and doesn't need any third party library. It is easy to implement and solves the problem of sharing states at different levels of the component.
But on the other hand Redux is the Industry standard and has support for middleware to perform async actions.
If I choose Context API how can we manage API calls with it. Also do you think it is a good idea to use context for a large application where we might need state objects extensively.
The design benefit from Redux is that the action does not implement. An action is an indication that something happened (for example SAVE_PROFILE_CLICKED) but the action doesn't do anything (like connecting to api, sending data and saving response in state). You can do this with context api but the separation isn't enforced as much and you won't have the redux devtools. The pattern is called event store/sourcing. You could change the reducer and replay the events to see if your changes work and create a consistent state, testing is easier, extending is easier, logic is better isolated and probably many more benefits to be had.
The design also separates writing to state (reducer), side effects (thunk) and reading from it (selectors). This pattern (writing/reading separation) is called cqrs. Your query/selector is separated from the command/reducer. This gives you easier testing, isolation of logic, less chance of duplicate implementation and probably many more benefits.
You can still make a complete mess of your project when using Redux and not fully understand it so using Redux does not guarantee anything.
If I choose Context API how can we manage API calls with it.
You can do it any way you like it, the question is too general to answer.
Also do you think it is a good idea to use context for a large application where we might need state objects extensively.
As stated before; Redux is no guarantee your project won't be a mess. It will give you the tools to implement certain patterns with more ease. Make sure you understand it and it's patterns. Most example applications don't demonstrate why Redux is so powerful as the problem they implement (counter, todo app) isn't complex enough to even warrant using it. I can only advice you would write code that you're comfortable with and can understand.
I've used Meteor a fair bit and love it, the publish/subscribe model, the way the whole framework is thought out, the ease of writing the server-side code...and I've used React with Meteor, and that's also cool.
However I've recently done a non-Meteor project in React/Redux and there's a lot to love about Redux. It's more effort to set up but the single point Store and all the associated tools/systems are very nice.
My web app will do a lot of database interaction and needs optimistic UI.
So I'm wondering whether to use Meteor/React/Redux for my next project, especially as there are some limitations in MiniMongo (e.g. no support for arrays). However I'm not finding a lot of relevant tutorials on how to hook them together, for example this one is nearly 3 years old now. This makes me doubt whether many people are using this setup, and whether I'll be able to get it working easily: I know from past experience that I need step by step tutorials to get past the initial hurdles with a new setup, then after that I can work things out for myself.
I'll use Meteor/Redux next for sure. I know them, I like them. The question is whether adding Redux is worth the overhead? I hope this is a suitable question for StackOverflow, if not I will try posting it elsewhere.
I'd like to hear reasons to use or not use Redux with Meteor/React, and any recommendations for tutorials. Thank you.
I think Redux is applicable in the non-meteor world, although there are alternatives now with graphql local state or the use of the React context api (which, thanks to React Hooks, is no longer deprecated)
Anyway, back to the story...
I have two separate Meteor apps, one that uses Redux, and the other that doesn't.
Redux works well with Meteor, it does the async thing quite well, but it adds a whole lot of complexity for arguable benefit. In a non-meteor app where you are doing much more in the way of orchestrating asynchronous API calls, then it makes total sense, because you can effectively decouple the data handling from the UI.
But in a typical Meteor app, use of publications and subscriptions means that the data flows naturally anyway. A UI button requests a back end action. The Meteor method does the work, and updates the database, and that data is updated in the UI automatically.
Let's take a scenario that I implemented recently. Members of my app need a Working With Children Check. They are issued a number, and when we are processing membershio renewals, we need to check that the number is still valid. This is initiated by a button on the UI, which calls a Meteor method, which in turn does an API call. The method simply updates the results of the check (even if it fails) into the member's database record. A return value from the Meteor call allows us to do a toast notificaton for the user, and pub/sub looks after updating the new status in the UI.
This could also be done with Redux, but pretty much all of the above code needs to be done anyway.
My preference is away from Redux, as there are alternatives, and it feels like it is a level of engineering that takes you away from writing your app.
I'm developing Web project with react.
But bigger code size the speed is slower. And All code in one system is easy to be complicated and hard to maintain
Is there a way develop by each component with redux, side effect all in one module?
For example, modulizing one component(comtainer) with is's action, stores, side effect. And attach main code with build system..
At the end of the day, a single store will contain all state in redux. The exception to this, is if you choose to run two seperate apps on the same page - but they wouldn't be linked in any way whatsoever (so ignore it).
However, you can use combine reducers to join reducers from multiple components into one store while keeping them separate. For the majority of apps this will suffice completely, and I would find it hard to imagine it would cause performance issues unless it is set up incorrectly.
Your question doesn't lend itself to one concrete answer, but rather patterns. I would look into "ducks" for redux - its not a technology or library, but rather a pattern for keeping your stores and components modular.
Ducks: https://github.com/erikras/ducks-modular-redux
Explanation: https://medium.com/#scbarrus/the-ducks-file-structure-for-redux-d63c41b7035c#.36dsdqd5q
Personal favourite structure doc: https://hashnode.com/post/tips-for-a-better-redux-architecture-lessons-for-enterprise-scale-civrlqhuy0keqc6539boivk2f
If you still feel like redux doesn't align to your modular app, you can consider not using it - sometimes there is no need for it. https://medium.com/#dan_abramov/you-might-not-need-redux-be46360cf367#.p7j6cioou
I'm new to Redux. I'm having trouble understanding the value of actions and reducers vs. components directly modifying the store.
In Redux, your React components don't change the store directly. Instead they dispatch an action -- sort of like publishing a message. Then a reducer handles the action -- sort of like a message subscriber -- and changes the state (more precisely, creates a new state) in response.
I feel like the pub/sub-like interaction adds layers of indirection that make it harder to understand what a component is actually doing -- why not just allow components to pass new state to the Redux store directly? Would it be a bad thing to inject something like this.props.setReduxState into a React component?
I'm starting to understand the value of why the state itself needs to be immutable (related question -- Isn't Redux just glorified global state?), related to checking for updates to see which component props need to be updated in response to state changes. My question is the extra action/reducer layers vs. manipulating the store directly.
I had some very similar questions when I decided on going down the Redux rabbit hole. In my case I was developing relatively small apps and components using just the React internal state, which still works really well. It was only when the app and the number of components grew much larger that setState became somewhat unwieldy.
I don't think this is emphasized enough - you don't always have to use Redux if you're working on a relatively small app or a few components that are easy enough to keep track of without a robust immutable store solution. There is a lot of necessary boilerplate just to get started, which can be overly time consuming in some instances.
That being said, React + Redux is a great design paradigm to follow once you are used to it and have your own boilerplate you can call upon. Redux essentially favors props over state, which forces immutable design as you (generally) can't mutate props. This is what makes the Redux DevTools "time machine" possible, along with all of the middleware that you can throw at your store as previously mentioned by others.
Middleware is a big part of it, especially with the advent of more precise solutions for sync and async tasks alike like redux-saga (https://redux-saga.js.org/). IMO "thunks" (https://github.com/gaearon/redux-thunk) are easier to grok than sagas when you're just getting started, unless you're already an expert with generators, but sagas are much more predictable and therefore testable in the long run.
So instead of having a separate internal state for each component, you can have a set of actions / reducers that you use instead, knowing that you can't mistakenly mutate the state. I've found the combination of ImmutableJS (https://facebook.github.io/immutable-js/) and Reselect (https://github.com/reactjs/reselect), which gives you composable selectors - to be great for this. No need for Object.assigns or tons of spread operators, it creates a new object for you.
I wouldn't be in a hurry to convert existing non-Redux projects into Redux, the workflow is different enough to cause significant confusion, but you'd be hard pressed to find boilerplates for new projects that don't already have Redux in their workflow. Such as "React Boilerplate" (https://github.com/react-boilerplate/react-boilerplate), I know this kind of blew my mind at first, but definitely worth getting a feel for. It really tests your functional programming chops.
In the development process, you often need to know who and how has changed the state. Mutating state by emitting actions allows you to keep answers to those questions.
Actions are payloads of information that tell the store how it should be modified. This information is represented in form of plain javascript objects which allows this information to be logged, serialized and stored. Since all the history is "remembered", you can later replay all the chain of actions for debugging or testing purposes. Together with a tool like Redux DevTools it makes development process really easy and amazing. Since all the store modifications are logged to a monitor, so you can see how and when was the state modified on every step. Even more, you can go back or forward through the actions chain.
Another benefit of having all mutations centralized in one place is the fact that it's easier to take control over the state. That guarantees, that all mutations happen one by one in a strict order and no callbacks can make the application behavior unstable. It also allows to keep in one place functionality that is common for some actions, or in other words to apply middlewares.