My problem is the following.
I have a component that I want to be stateful, and the state based on some ids (per user and per task basically) and this state is saved in my database.
Following some tutorials I managed to do a stateprovider that requests information through ajax requests.
Though I still have a problem since the restore event is only triggered when reloading the page, but not on task change.
Would there be anyways to trigger state change when tasks are opened.
Because the problem I have right now is if I force the restore, it happens but the task will somehow still be opened with the previous state (I guess because of the fact that the provider is asynchronous?)
Related
I'm fetching data from the server to initially populate a form. This form is then edited by the user. Those modifications shouldn't be send be immediately send to the server however, only if the user presses a publish button. I don't want to store serverside draft state either. The modifications still need to be "state" in a way, that multiple components read from it and should be updated immediately as the user types (so I can't just keep the data in the DOM and get it from there on publish).
One way to accomplish that would be to disable refetching in SWR, modify the cache manually with the mutate() or useSWR() hook and a local "fetcher" (which just returns local data instead of fetching from the server). On publish, it does basically the same, only with the "server" fetcher, which sends the current cache to the server.
The other option would be to keep the client modifications in a seperat state manager.
I think both would technically work, so I'm asking more for the recommended way here.
I’m making a simple app with react-routing component.When user enter in /config path, it open a configuration page where he can choose element from select.
After this, user save data and the application set state of main component correctly (App.js). Then i make a “view change” using history to return in home (/ path).
The problem is : if user click on second time in /config routes, it lose all previous change made on DOM and it seems to be a new istance.
How i can preserve user interaction after first change? I cannot understand if i need to make a state inside this (Config.js) or there are an alternative solution.
Thanks for all
If you have an app level configuration which should be preserved between renders/navigation you should consider using some sort of a state management like Redux or you should store your config inside sessionStorage/localStorage (sessionStorage keeps track only while your browser tab is active = not closed. localStorage saves for the future when user closes and reopens your app).
Learn more about Web Storage API on how to use sessionStorage and localStorage.
NOTE: When you navigate away from your component, it gets unmounted which means that the component's state is destroyed/trashed. That's probably the situation you're facing now with your project.
You need to store the data/state/config somewhere. If it's just a few things (nothing heavy or complex), you can use localStorage (it saves the data between sessions, doesn't matter if you close tab and open it again)... But if you need to have a greater control over the app's state you should consider diving into Redux Store.
Have in mind that by default redux doesn't support data persistence so you'll need to plug-in Redux Persist package to achieve that (it's like saving in localStorage, but now the whole Redux (with all the states) will be saved between sessions)
I am not sure what you mean by
lose all previous change made on DOM
Where do you store these changes made and could you not check for this state and render the contents of the /config component or even the component itself depending on whether or not the changes to the state have been made?
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 wanted the list of users to always be in sync with the MongoDB database,
I created an action that dispatches a refresh call to refresh the list of users.
What I have right now is an interval that dispatches the refresh call to refresh the list every 1 second, but I think it's a little hack to do that.
Is there a better way to refresh my list and re-render them through my React views?
What you are doing right now is okay but is expensive, specially if your browser tab is not active (please note that setInterval/setTimeout get less priority by browser if the tab is inactive or minimized).
You might need to explore using RxJS which has the capability to create periodic caller functions and you can subscribe to it in your react view.
Example - https://www.learnrxjs.io/operators/creation/interval.html
Single page apps require careful management of events, DOM elements, and javascript objects in order to avoid leaks.
We're going to manage memory and squash leaks as best we can. That said, the application is large, uses many libraries, and could be left open for days at a time.
We need a safety valve.
I'm looking for ideas on how to unobtrusively trigger a page refresh in a single page app as a way to force the release of memory.
One idea is to detect when the user is idle for more than N minutes and do a refresh then, because it's unlikely to interrupt them. Much of the application state is saved in the URL using AngularJS ui-router, so this will work some of the time.
The problem is that while some state is in the router, not all of it will be. The user could have unsaved changes, or have some modal or flyout menu open which isn't in URL state. A solution could be to detect user changes and ban a refresh if any changes have taken place that aren't in the url. I don't see how to implement this generically though. Maybe we just put everything that's even a little bit important into URL state.
Another idea is to watch the application state change event $stateChangeStart and, every Nth time, do an actual browser navigation to that URL instead of just an app state change. This will never result in lost "sub-state", but will cause a slower page change response and a screen flicker. Maybe every 20 screen changes this is OK though.
Does anybody have any better ideas?
Just an idea on unsaved changes and data:
I have an a single page app that in one section has several tabs each containing a form. When each form becomes "dirty" it triggers a notification to the Main Controller, and sets a flag for that form. When a user saves a particular form the flag becomes unset. If the user tries to navigate away - before the route change occurs, it checks to see if any of the flags are set and then notifies the user via a modal that some particular information hasn't be saved. The user can then decide whether to continue with the route change or go back and save the data.
This could easily be modified to perform the same check on page refresh and if there is unsaved data either cancel the page refresh or save the changes to the browser's local storage for recall after the page has finished refreshing.