I am working on react app + redux.
I have some HTTP requests that I don't think that should be in the state of my app. (for example : in case of autocomplete, I fetch only relevant data, I don't have to use this data anywhere but in the specific input).
Is it a bad practice to have folder of "statless services" inside an react-redux app?
Do I have to keep every request result in the state?
What about POST and PUT requests?
Thank you.
Speaking broadly is not bad to keep something out of the state if it's not relevant or shouldn't influence render or state.
Take for example a live graph that updates every second. You don't want it to trigger a re render every time it updates.
Or some external service for example Google Maps Auto Complete. It takes control of the dom, does external calls and so on but at the end of the day what you want for your app is the location when the user perform some action.
All the several state changes that it does on the map and on the info until the user decide that there is his location is not relevant and shouldn't be a part of your state.
This could be opinion based... It's a bad practice, that's transient state no one else is interested in.
I suggest you to use https://redux-saga.js.org/ to avoid pollute your logic with side effects and take care of this common transient states.
Related
Data usage really matters for my targeted users. So, I am looking for an APPROACH that'll help me reduce the number of data fetching during react rerender cycles in React and React-native App.
Let's say I have a page that renders all the Items fetched from an API. Since the API's data can be updated at anytime, I am obliged to re-call the API whenever the user displays this page.
IS THERE ANY WAY FOR ME TO KNOW THAT THE DATA HAS BEEN UPDATED WITHOUT BEING OBIGED TO RECALL THE API?? Because I think that the less HTTP requests I send the less mobile data I consume (Maybe I am wrong... I don't know)
I thought of implementing a solution with Redux and Socket.io :
I wanted to prepare an event called data-updated that will be managed by socket.io and whenever one of the users performs an action that updates the item lits (The API data), the data-updated event will be triggered and all the connected users will be notified. Then in the data-updated event handler I will update the item list state slice in the redux store.
My worry is that since socke.io keeps the connection between users and the server alive during the whole session, Won't this approach consume even more Mobile data than recalling the server at any rendering??
You can proceed with graphql with mutations and its caching mechanism, its pretty cool and if I mention if it is handled efficiently you can run your application in 2g network also with speed. Checkout its usage and advantages over REST you gonna love it. https://graphql.org/
Another way is by using redisCache but personally I've not used it though you can check.
You can use React-query lib for data fetching, updating, caching etc.you can read more about it but read its docs.
https://tanstack.com/query/v4/?from=reactQueryV3&original=https://react-query-v3.tanstack.com/
Let's figure it out,
An user performs a login submission, so app shows instead a
Submit button a Spinner, a self contained state whose help us (isLoading).
Okay, when application send to saga login action we can pass a callback
for set false loading state when login submission has successful or failure.
Some experts will say, manage loading state in reducers, but carry to all whole application
loading state, for some specific action not sounds good.
The problem with callbacks is that the architecture doesn't guarantee that the callback gets called or that it won't get called multiple times. That is because redux actions are essential events - where each event can be handled by 0-n handlers (or sagas in our case).
Of course at the time of writing you know that that particular code is handled exactly once, but for anyone else this might be hard to grasp unless there are strict rules in the project how to handle this.
At the same time, you are right that putting local state to redux store isn't great. I usually deal with this by moving the data logic to its own structure. So e.g. loading collections of items from server is no longer local state of some component bur rather global data state that can be used and reused by multiple parts of the applications. This will also make it easier to have custom caching logic for the data cross whole application etc. However, some local component state in redux is still unavoidable for some specific backend calls.
In terms of future, I saw some attempts at useSaga hook, which would work on top of local useReducer hook and therefore local state, however the implementation for such logic is still limited because the current react hook api lacks certain functionality that is necessary to make sure this works well with react commit phase, render bail outs, reducer reruns etc.
I have a question about calling API in react.
Example in the website. We have a lot of page. Each page has a lot of components. And each component has its own data need to get in server.
I see we have two way to call API is:
First. We call all API of each page in a root of each page then set the data to state. After that, we pass data to children Component.
Second. In each component, we call its API to get its data then set the data to component 's state.
So which is better. I need an explain about that.
Thanks you,
There are many ways to pass Data through out the components.
If the application is small and there are small number of child components you can go by making calls in Root folder.
There would be some components that always doesn't render and only rendered based on specific conditions at this point you can go by making calls from that component.
Using redux and redux thunk is always an option if the data is needed in many components and data can be accessed at any point of time.
As noted in the previous answers/comments you could do either one of these. If you plan to use redux it might be easier to chain the api calls in a single action w/ thunk that gets ran on main component load.
Context or Redux would do you well so you don't have to pass tons of data through prop levels.(prop drilling)
I would suggest Redux, IMO context gets too cluttered and by the time you've properly atomized your code to clean up everything you may as well have just went through the overhead of adding redux.
What you should ask yourself is-
Does it make sense to have all this data load at the same time?
Is it appropriate for some api calls to be made from the components that will use them?
You have creative license to do what works best for you.
I'm building a real-time "lobby" type web app that hosts multiple users (2-8 at a time), where the state of the lobby is shared among the users. The UI is built with React. Each user establishes a websocket connection to the backend upon joining the lobby. At this time they receive the full global state of the app as a JSON object (its size should not exceed a few kilobytes).
I'm having difficulties conceptualizing the precise state maintenance scheme, and would like to hear your views about it, once I've described the situation in more detail.
The lobby presents to the users a number of finite resource pools, access to which is shared by everyone. The users will move these resources between each other as well as to and from the pools. My current thinking is that the full state of the lobby and all of its resource pools is stored and maintained exclusively in the backend. When a user wants to move a resource e.g. from a pool to themselves or vice versa, or to change the visible state of a resource, this is done with JSON messages sent over their respective websocket connections.
Each action they perform causes a message like this to be sent over the socket (simplified):
{
"action": "MOVE",
"source": "POOL1",
"target": "user_id_here",
...metadata...
}
The users send these messages concurrently at arbitrary times and intervals, and the backend (using a Python asyncio-based server and a data store still to be determined) receives them serially, reconciles each one with the global state in the order they arrived, and then sends the full updated state of the app to every user over their websocket connections, for every single message received. The user who performed the action that triggered the state update additionally gets a status object informing them of a successful transaction, which the UI can then indicate to them.
When a user sends an action message that is impossible to reconcile (e.g. another user has exhausted a resource pool just before their message requesting a resource from that same pool came in), the app still sends them the full up-to-date state of the app, but a status object is included, containing information that the UI uses to inform them that their action could not be performed.
So far, so good. Given the types of actions, types of resource pools, number of users and size of state objects that are to be expected, the frequency of updates should not become a problem, neither in terms of resources nor bandwidth use.
To clarify: none of the actions that the users perform in the React UI mutate their local state in any way. Each and every action they perform is translated into a JSON message like the example above, and the result of that action will be receiving the updated full state of the app, which fully replaces the previous state that React used to render the UI with. The React-level app state is ephemeral, only used for rendering it once. All renders exclusively happen in response to state updates over websockets.
The one area that I'm having difficulties with is how to structure that ephemeral state on the React side so that rendering the updated state object is as quick and efficient as possible. I'm a backend guy and have no prior experience in building a React app of this nature (I last used it four years ago in a really ad-hoc manner, passing props to deeply nested child components, with state stored all over the place). I'm not quite sure what facilities and tools to use.
For example, I could use a top-level context provider with the useReducer hook, touted by many as a "Redux replacement" (which it technically isn't). Or, I could use Redux, but does it actually add any value in this case? Or something else?
Given that the whole state is replaced as a result of every action of every user, what is the best, most efficient, least render time-requiring way of structuring the React side of things?
I would like to suggest that you do not send in the entire state of each and every user over the network instead just send in the modification and let the individual users apps perform the change handling. Once you make this change you could make use.of redux and store the states in a reducer. Also doing this will help you avoid a lot of re-renders as the object references will not change for a lot of your components,
Another thing to add here is that you can store the redux state in the localStorage when the session is terminated
FurtherMore, the one problem that you could have here is that when the user re-connects, he might not get the changes that happened while he was online.
To solve this, you can maintain a transaction id for each user so that the user is sent all the data post that transactionId till the current state by the server and then the app can process and update the transactions
Or the other approach if to completely fetch the data when the user connects for first time or reconnects.
As far as using useReducer or Redux is concerned, you need to decide that based on the complexity of your App.
Cases where the app is small might easily be covered with useReducer and useContext but if you states are complex and you need to maintain multiple reducers, you should go ahead with Redux as it provides moree flexibility with data storage
EDIT:
If the only solution for you is to send the data totally to frontend and let the frontend render it, then you need to divide your frontend code into various simpler modules as much as possible so that no component is using a a complex state.
Once you do that you can make use of shouldComponentUpdate or areEqual parameter to a class component or functional component respectively.
The idea here is to compare the previous and current value that you get from props and let go ahead with the rendering logic or not.
You can store the state as it comes to a reducer inside the redux state, that way, you would be able to implement selectors that are memoized and are able to return data which doesn't change if the actual value hasn't change.
Also while you are using connect for your React app component, its actually a functional component, so unless mapStateToProps returns a value whose reference changes, it will prevent the re-render itself since its a PureComponent
I would strongly suggest, you go through the documentation of shouldComponentUpdate, React.memo and redux. Also look into reselect library that helps you implement memoized selectors
I’m using Redux to manage the logic of a music player. When it’s playing something and suddenly fails, I want to be able to intercept that action and make the player start again, but only n times, as I don't want to keep automatically retrying forever if the problem isn't recoverable.
I think a middleware is a good option to implement this, but I’m wondering if I should store the number of retries already done for a certain item either in the global state, or locally in the middleware.
A more general question would be if a Redux middleware should contain any local state at all, I mean, state that only it cares about.
In my opinion (and based on limited information about your specific project):
you should configure the n value via the middleware constructor, and
you should store both n and totalRetries in private variables of the middleware.
Why?
Choosing where to store your middleware state shares similarities with deciding between component state and redux state. You can use the same questions as a guide:
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)?
Do you want to keep this data consistent while hot-reloading UI components (which may lose their internal state when swapped)?
As Dan Abramov said:
The way I classify it is when ever state needs to be shared by multiple components or multiple pages and we need to persist some data over route changes, all that data should go inside the redux store.
You can map this idea from components to middleware by rephrasing "…persist some data over route changes…" to "…persist some data over [insert relevant boundary here]…", for example closing and relaunching the app.
The totalRetries doesn't seem to represent a meaningful state of the application. It has to do with some "behind-the-scenes" I/O operation that wont persist across closing the app or sharing app state with a debugger. One might even argue that you should not expose it to other components via redux state, lest they rely on (potentially shifting) internal workings of your middleware.
redux-saga, etc allow us to write this type of functionality in a very neat and testable way without having "exposed wires" in the application state or module namespace. You could use a saga to encapsulate your entire "play audio" behavior.
Exporting a reducer and then accessing its compartmentalized "public" state from your middleware introduces quite a bit of unnecessary complication.
If you want to expose totalRetries and n to other components, you may do so via an action, such as PLAY_AUDIO_RETRY with the action containing both variables in its payload.