If, in React, I can use connect to map state and dispatch to props, and the component I used connect on will auto-render when the Redux state (and hence props) change, why would I ever need to use subscribe?
You're talking about Redux and Redux-React (which provides the connect function, specifically for React components). Take a look at how Redux-React is implemented.
connect is just a React specific abstraction over subscribe.
What happens if you aren't using React? It's totally possible to use Redux with other frameworks or even just plain Javascript applications. In these cases, there needs to be a lower level mechanism for subscribing to changes in state.
They have also updated their documentation to speak to this regarding subscribe
It is a low-level API. Most likely, instead of using it directly, you'll use React (or other) bindings. If you commonly use the callback as a hook to react to state changes, you might want to write a custom observeStore utility. The Store is also an Observable, so you can subscribe to changes with libraries like RxJS.
Related
I am building a web app where redux is configured and app is fairly large.
Now I want to store some user preferences which will be available as part of an API respopse.
As this data is required to the majority of components I am planning to store data in the context and wrap application using the context.
I have Few questions regarding approach.
Will considering context impact the performance?
As Redux is already configured which internally uses the Context. So should we continue to use redux for user data.
Is it good practice to use Redux and Context together.
Context and Redux are very different tools that solve different problems, with some overlap.
Context is not a "state management" tool. It's a Dependency Injection mechanism, whose only purpose is to make a single value accessible to a nested tree of React components. It's up to you to decide what that value is, and how it's created. Typically, that's done using data from React component state, ie, useState and useReducer. So, you're actually doing all the "state management" yourself - Context just gives you a way to pass it down the tree.
Redux is a library and a pattern for separating your state update logic from the rest of your app, and making it easy to trace when/where/why/how your state has changed. It also gives your whole app the ability to access any piece of state in any component.
In addition, there are some distinct differences between how Context and (React-)Redux pass along updates. Context has some major perf limitations - in particular, any component that consumes a context will be forced to re-render, even if it only cares about part of the context value.
So, yes, you can use them both in the same app, in the same way you can use a hammer and a screwdriver together on the same construction job.
For more details, see my posts:
Why React Context is Not a "State Management" Tool (and Why It Doesn't Replace Redux)
React, Redux, and Context Behavior
A (Mostly) Complete Guide to React Rendering Behavior
Will considering context impact the performance?
Since you want to share user preferences that (I guess) do not change often, you could use a React context to share that data.
But performance issues arise when you put multiple different data in one React context that update at different rates. This is because every component that uses the context will be rerendered even if the part of the context it is interessted in did not change. In this case you can split the context and use one context for each part of the data.
Since you want to use the context to share an application state, you should use Redux. In Redux you use selectors to select a part of the application state. This useSelector hook is implemented in a way that it only triggers a rerender of the component if the selected part changes. You can even pass it an equality function if you want to change the way state change is detected.
As Redux is already configured which internally uses the Context. So should we continue to use redux for user data.
I would say: yes, continue with Redux.
Since you already use Redux you should not spread your application state management over different concepts. Put the user settings in the Redux store (like any other application state) and don't handle them special.
Is it good practice to use Redux and Context together
Well, Redux is based on the React context. So if you use Redux it is already a good practice.
If you mean using both for application state management, I think you should go the Redux or the React context way. Mixing them makes it harder to understand where state is managed.
I had an interview, where the interviewer asked me if redux uses context API internally. Pls provide a detailed description if yes. Thanks
Redux doesn't use context api, it's a javascript library for state management. You can use Redux with any application- like (react, angular, vue, svelte, etc). However, for using redux with react applications, you need react-redux which is the official react bindings for redux.
react-redux uses React's context api to make the redux store accessible to all components. The reason why you need react-redux is because, React uses virtual dom - which means you can't manipulate the DOM directly. In other libraries like angular, we use the NgRx library (For angular).
Internally, React Redux uses React's "context" feature to make the
Redux store accessible to deeply nested connected components. As of
React Redux version 6, this is normally handled by a single default
context object instance generated by React.createContext(), called
ReactReduxContext.
Source
Yes, but differently than if you would be doing it by yourself.
If you were to use Context manually, you would usually do value propagation - passing the current state value down the tree. This can lead to very inefficient rerendering behaviour. See this article for a deeper explanation.
React-Redux on the other hand uses context for dependency injection. The store is passed down the tree and will never change, never triggering a rerender. All the rest is done by Redux internally, using manual subscriptions. This is much more performant.
This question was already asked here before, however I didn't find yet any proper answer, just wonder if I missed anything or if indeed this is currently not possible.
Specifically, there are 2 main differences between hooks & redux-saga (or any other middleware):
in redux-saga I can trigger code execution on action dispatch, while in hooks I can trigger code execution only on state change. These 2 are not always equivalent
hooks must exist in context of component, however some "background" logic (such as initialization, location detection, etc), is not related to a specific component. In redux-saga I have the flexibility to define it in "global scope", while in hooks I must attach it to some "random" component (probably App or any other high level component).
So, is it possible to "bridge" somehow between these 2 approaches, or should I simply pick the most appropriate technique for each specific case ?
They are different tools to solve different problems. Hooks work internally to a functional component's state and lifecycle. Redux works internally to an entire react app's state and lifecycle. Sagas help wrangle asynchronous effects like external data fetches.
Generally speaking you want to limit the scope of variables and logic as much as possible. If a specific piece of "state" is only relevant to a single component, then keep it in component state. But if several components or the application itself needs it, then store it in app state. Same applies for asynchronous calls. If a single external call is used by only one component, keep it there, but if multiple components can make the same external async calls, then let the sagas handle them.
You are free to use as much, or as little, as is necessary of either in each component to solve your problem.
In Redux-saga you can execute code only on action dispatch. Hooks are more generic, for example with the useReducer hook you can trigger code on action dispatch, with useEffect you can trigger code on mount/update/unmount etc.
Redux-saga also exist in context of a component, or more precisely, whole Redux exists in a (usually top-level) store provider component and Redux-saga is only one of its middlewares. So basically if you have some global app logic and put a hook for it in your App component, it is not some random component, it is the right place to put the logic to.
I've also recently found a simple library https://www.npmjs.com/package/use-saga-reducer that introduces sagas to React's useReducer. (I'm still not sure it is a good idea - just because you can doesn't mean you should, for me hooks async functions are usually enough, but it is at least interesting)
I've been using Redux for most of my React applications.
I think I will start using XState as I don't have to use effects as a plugin all the time.
And I think is a more complete pattern.
One thing that I want to understand is it's connection with React (hooks and classes) and it's interaction with reactive programming in general:
Can I (and should I) use XState context as Redux data store in the same way, having a single source of truth on a shared by React Components way? Will my components be able to "connect" and "mapToProps" the XState context and rerender only when those values changes and not every time the state machine state changes?
From what I understand Redux lacking side effects is so it can adhere to a pure functional paradigm. But that breaks with side effects usage, that is a lot of times needed in web apps or games for example.
Thanks in advance!
XState can basically manage your global state in Redux (or other state management libraries) if you want to, but it won't replace connecting with React as Redux does. You should view it as an extension to Redux and you would still need to follow the patterns used in Redux, but use XState to perform them. A few examples:
Redux state can be represented as anything, so it can be a XState machine state + XState machine context.
Redux actions should basically trigger XState machine transitions. They can also trigger async actions (https://xstate.js.org/docs/guides/communication.html#invoking-promises), so you might not need something like redux-thunk to deal with that. You actions will become much simpler, but the actual handling is moved to the machine.
Redux reducers usually return a new state, therefore they are the outcome of a XState transition.
You can probably find a way to connect this all together (did a similar thing with Vuex recently). The XState machine would simply be a singleton called from Redux entities, but you would not "embed" the machine inside Redux.
You would also still need to use the react-redux tools as before and the machine would never really be exposed to the actual React components (except you want to use XState machines for local state as well).
What's the difference between A) using the connect method of connecting state and dispatch function to a component and B) simply having functions in a component that do the dispatching as well as accessing the store as a global directly?
(Not ES2015)
Quoting from the Redux FAQ on importing the store directly:
While you can reference your store instance by importing it directly, this is not a recommended pattern in Redux. If you create a store instance and export it from a module, it will become a singleton. This means it will be harder to isolate a Redux app as a component of a larger app, if this is ever necessary, or to enable server rendering, because on the server you want to create separate store instances for every request.
I also recently wrote a Reddit comment on why you should use React-Redux and connect instead of talking to the store directly. Quoting that:
First, while you can manually write the code to subscribe to the Redux store in your React components, there's absolutely no reason to write that code yourself. The wrapper components generated by React-Redux's connect function already have that store subscription logic taken care of for you.
Second, connect does a lot of work to ensure that your actual components only re-render when they actually need to. That includes lots of memoization work, and comparisons against the props from the parent component and the values returned by your mapStateToProps function for that component. By not using connect, you're giving up all those performance improvements, and your components will be unnecessarily re-rendering all the time.
Third, by only connecting your top-level component, you are also causing the rest of your app to re-render unnecessarily. The best performance pattern is to connect lots of components in your app, with each connected component only extracting the pieces of data it actually needs via mapStateToProps. That way, if any other data changes, that component won't re-render.
Fourth, you're manually importing the store into your components, and directly coupling them together, thus making it harder to test the components. I personally try to keep my components "unaware" of Redux. They never reference props.dispatch, but rather call pre-bound action creators like this.props.someFunction(). The component doesn't "know" that it's a Redux action creator - that function could be a callback from a parent component, a bound-up Redux action creator, or a mock function in a test, thus making the component more reusable and testable.
And finally, the vast majority of apps built using React and Redux use the React-Redux library. It's the official way to bind the two together, and doing anything else will just confuse other developers looking at your project.
For more info, see:
The Redux FAQ section on performance
The Redux FAQ entry on connecting multiple components
The Redux FAQ entry on components re-rendering too often
The Redux FAQ entry on importing the store directly
The Redux Performance section of my React/Redux links list
And finally, my blog posts Practical Redux, Part 6: Connected Lists, Forms, and Performance and Idiomatic Redux: Why use action creators?.
Source: I'm a Redux maintainer, and author of the Redux FAQ.