Flux - How does store should notify error? - reactjs

Let's say component invoked an action and store tries to perform some operation but it couldn't, so store is trying to report the error back to view so user can be aware.
I can think of two options to handle this.
Have store emit an error event and then view components can listen to this event like they listen to change events and show the error to the user.
Store can add the error to the state object and fire a change event, then the the view components can check the error on the state objects and display error message accordingly.
Or is there any elegant way of handling this ?

Store normal and error informations in the store state is a better way to do that. In your scenario, you may need to show a error dialog or something else in order to tell user something is broken. That is, you have to rerender your components according to different states, so just put the error information in your store state and emit a change event.
Put everything which makes components change in the store state. That allows everyone to know your data flow easily and quickly.

Related

React-Hooks : Listen to Events across independent Components

My App has following sample structure:
<App>
--<Users>
------<UserList/>
--</Users>
--<UserManagement>
------<UserList/>
------<AddUser/>
--</UserManagement>
</App>
In <UserManagement> I use a state variable to listen to the mutation that gets done in <AddUser> so that the <UserList> directly updates after the mutation has been done.
Now if I add a user and go to , the <UserList> there does not re-render as it has no idea about the change in the database. I don't know on what for example a useEffect hook should listen to.
I thought about using React Context provided in <App>. But I'm not sure if this is the right solution. I'm using a simple sqlite database not providing any subscription tools or sth.
Can anybody provide me a hint?
I hope its understandable with this, otherwise I will provide code.
Thanks!
There are two approaches:
you can pass the same state variable in to the component that signifies a change in user list. use the useEffect hook to listen for this variable to get the user list again from the database.
create another state variable in that basically sync up with your database. You pass this variable into the component. when the user is added, you add to the sql database and this variable. You also pass this same variable into to display the users. Keep in mind that this approach basically makes a copy of the user list.

Initialize state from props using rehydrated Redux store

In my application I have a dialog window on which there are multiple input fields. What I want to do is to save user's input in the component's own state and only afterwards, say, inside "onClose" of the Dialog send the input to a redux store using "dispatch" function.
This way the dialog component would keep field data inside its own state.
The problem that I face is that I'm not sure what the best way is to rebuild dialog component state from information contained in the redux store.
If one refreshes the page with F5 or simply reloads it, then components lose their state and fields will appear blank, regardless of the fact that rehydrated redux store still contains valid input information.
The question is then, what is the best way to set components state from props? Moreover, doesn't it seem like an antipattern? What are some common techniques for such task?
One possibility is to set field values directly to those contained in "props". This would, however, imply that every small change of the input fields will result in copying and modifying redux store, which is slow & inefficient.
Usually building a state from props complicates code a lot, you have to map props both in constructor and getDerivedStatesFromProps.
I prefer to write component functions which return value based on passed props.
As you mentioned it may impact perfomance, to fix it you can use memoize-one library.
For more details you can check the following answer

Automatically calling action AFTER redux state is loaded

I have a app in which users can build a "Quote". So far I've been adhering to "idiomatic" redux (or something close to it) and it's been working out well.
However, I'm struggling to deal with a fairly simple scenario:
When the page is first opened, I fire an async LOAD event which retrieves info from the server needed to build the quote (products, inventory, previously saved line items, etc).
I need some way to be able to automatically add a specific line item(s) to the quote first it's first opened.
I've added a defaultLineItems property to my LOAD payload, but to fire the addLineItem(product, inventory, options) action, I need data from the productReducer, inventoryReducer, optionsReducer. The lineItemReducer could look at these defaultLineItems and try to set it's state appropriately, but that would require having to rewrite a lot of BL typically handled by the actions using data aggregated from reducer memorized "selectors" (EG: defaulting price, quantity, currency translation, etc)
I can think of a couple ways to achieve this, but they all seem somewhat hack-ish (IE storing a flag in the reducer that says I need to fire an action and then running it when my root component props update). It seems like a react component should not be responsible for this type thing.
What is the proper way to do something like this?
Seems there are a couple different ways this can be accomplished but for me the most balanced approach between simplicity and design was to use store.subscribe in conjunction with a reducer to track the last action(s).
At it's simplest, this would look something like this.
store.subscribe(function() {
let state = store.getState();
if(state.lastAction.type === ActionKeys.LOAD){
console.log('load action fired!');
}
})
Please be aware that firing an action from store.subscribe will cause recursion so you need to be selective.

Responding to high frequency state changes in React.js / Flux

I have an application which receives messages from a server every 1 second and via socket.io these messages are broadcast to a react component.
My react component is using a flux style architecture, so it calls an action when a message is received which adds (or updates) a record in a collection in a store.
My component monitors changes on the store and then updates the UI when it changes. In this case, it draws a marker on a map.
The problem is that due to the frequency of the updates my component redraws all markers every second, which I don't want.
I'm looking for an approach to allow my map component to respond to changes in a collection in a store, but not have the state update every second.
I thought I could have a collection for the raw data, and then only update the networkGPS collection selectively in my store, but the component seems to change based on any property in the store as they all seem to be part of its state.
In summary I'm looking to:
Collect data every 1 second in raw form and add this data to a store.
Bind a component to a collection in this store which I update only when changes require a UI redraw.
What I think I need to do:
Either:
Avoid putting the raw data into the state of the store (at the moment I'm unsure how to declare a collection which is not part of the state)
OR
Make my component more clever as to when it redraws, so it doesn't try to redraw on each state change.
I'm not sure which is the most appropriate solution for the problem, any info would be gratefully receieved.
Sorry if the question is a little unclear, I'm new to react / flux. Please do ask for any clarifications.
EDIT
At the moment I am getting round this issue by storing an array of the items (map markers in this example) I want my component to display in the component itself :(
When the state changes and render is called, I intercept the state properties, decide if anything needs to change in the collection of markers and only amend them if needed. If no changes are needed, the collection in the component stays the same and no redraw is performed.
This is not ideal, I feel like I should be able to allow my component to respond to only specific state changes but I've not found it yet, still looking for a better answer.
There are a couple of ways to approach this:
1) Use shouldComponentUpdate to compare old props and new props, re-rendering only the new marker states.
2) Switch to a cursor-based state tree that automatically triggers renders only for views that are bound to the specific parts of the state tree that have changed. I believe Baobab is one such library. See also Om (written in ClojureScript) and probably a number of other Flux implementations.
Given the impact of #2 my vote would be to go the route of #1.
I am not quite sure what's the problem that you face with updates every second.
However, the one place where you can queue the updates is between the socket.io and calling the action.
Instead of calling the action every second, you could queue the updates before sending it across to react.

React + Flux change state while executing action

I am tempted to add error data to the store. For example,
var store = {
error: {msg:'',info:{}},
others: '',
etc: ''
}
On an error in the app, an action will update the error via the dispatcher, and the error panel will be shown to the user. The render of the error panel conditionally shows the div by testing the error msg state.
On the next user input, an action, i.e., userAction, the model state will be updated by the dispatcher. Problem: the error panel will still be shown, since the error msg state was not 'reset'.
The userAction will be setting other non-error state. Flux will emit a change for this change. Yet, if I follow the Flux model, a reset of the error should also be done here, in this action, but that would cause an emit, which tells to UI to update. Seems incorrect.
My thinking is:
1. Don't put this kind of stuff in the store? Or,
2. The store will reset the error state for every non-error update of state. Or,
3. Each action will also include an error state object for any state updates.
Currently my solution is to clear the error data within the store functions:
}, function(payload){
API.setError({msg:'',info:{}});
switch(payload.actionType){
case "BRANCH_SELECTED":
What is the non-idiotmatic way of doing this?
I'm new to React and Flux, so I'm sure this is newbie question. I'm using McFly as Flux implementation.
Though your question may have already been answered within the comments: I meditated on a similar question in my current React project and so I'm going to share my experience and outcome. I'm using fluxxor instead of McFly but that shouldn't matter here.
As flux stores should contain all application state and logic, I came to the conclusion that it's absolutely okay and in the sense of the flux architecture if you programmatically clear your error states conditionally within your store functions.
In my understanding it makes sense to keep error state handling related to a specific store within exactly that store (and therefore probably received and rendered by few listening components). As mentioned by #fisherwebdev, the store logic should determine the state of an error, specifically based on the action types it registered callback functions to. In your case, think of a BRANCH_SELECTION_ERROR type action being dispatched that causes error state to be set. On the other hand the BRANCH_SELECTED action type should always clear this state.
My concrete solution is in fact to call "private" store functions clearErrorMessages() or clearFormValidationMesssages() which simply clear state variables dependent on the actions being currently dispatched.
Global errors, i.e. errors that are somehow related to the application state like server communication timeouts, may go into some "appStore" and being updated or cleared in a comparable way. So e.g. router transitions may cause global error state to be cleared.

Resources