I have a task - to implement notifications/alerts on react+flux. Imagine the next situation user clicks on the button. After that I'm firing an action - for example "CALCULATE_ACTION" then I catch it in the MainStore. While processing this action in the MainStore I need to show the notification for user. Let's imagine I'm calculating something in the MainStore. Before the calculation I need to show notification "calculation has started". And after the calculation show "calculation has finished". I have a NotificationComponent which takes the notification text from the NotificationStore. So to show the notification I can trigger the "SHOW_NOTIFICATION_ACTION" and pass the text of the notification to this action, so the NotificationStore will catch it and set it to its state and NotificationComponent will be rerendered and notification will appear.
The problem is that I can't fire an action while other is in process. So if I've already fired "CALCULATE_ACTION" I can't fire "SHOW_NOTIFICATION_ACTION". Of course I can catch the CALCULATE_ACTION in the NotificationStore. But then I will be able to show only one notification - If I'll wait for the MainStore then notification will be after the calculations in the MainStore, otherwise - before.
And one more question- what if I need to show notification in the middle of the calculation?
My task is a bit abstract and I have more realistic one, but a lot of context should be explained so I've simplified the task to this example.
Does anybody has any ideas?
Any help would be highly appreciated!
In a typical react-flux setup, your components listen to changes in your stores.
Your component fires an action, your stores update, and your stores emit a change. (Stores should not fire actions)
In your (abstract) case, you could set it up as follows (with 1 action resulting in 2 store changes and 2 updates):
Front-end component listens to changes from BOTH NotificationStore as
well as MainStore.
This component fires a CALCULATE_ACTION.
NotificationStore listens to CALCULATE_ACTION. It immediately emits a
change. (without waiting for MainStore).
Front-end component receives this change event, and it retrieves some active_state
from NotificationStore (which in turn should probably read from
MainStore to determine active_state). You can have your component show this calculation busy' message.
Meanwhile, MainStore also received the
CALCULATE_ACTION. It starts the calculation, and as soon as it is
done, have it emit a change. Your component listens to this change
also, and will again retrieve the active_state from the
NotificationStore. Which is now abviously 'done' or something
similar.
Related
I have a Note component where a user edits a Note. Now, in my header for the app I have a button which can be clicked and you will be sent to the base product of the company - which is an external URL.
My problem is that the componentWillUnmount function (yes, this is the "old" component based API used in this particular component) does not fire and so any unsaved changes disappear.
Ideas?
I've tried adding an event listener in componentDidMount
window.addEventListener("beforeunload", this.componentWillUnmount); but my request is still getting cancelled before the redirect. I'm using apollo with graphql endpoints btw.
I don't see how rewriting to hooks can help here.
Looks like the problem is that you, actually, do not unmount component, but leave the page. React will never know about this event.
I think, you can use another approach to keep changes: send it to the backend while user filling the note. Or, maybe, easiest way is to duplicate changes in localStorage and then recover it on new load. But it feels less secure and, of course, limited by this browser/machine
Here are a few ideas you could try:
When the user clicks the button in the header, run a function/method to save the Note before redirecting.
Add an onblur listener to Note and trigger a function/method to save when Note input field loses focus
Add an onkeypress listener and save the contents of Note with every keypress (or every x seconds to batch the updates instead).
I have got an action "MODIFY_FIELD" firing on blur of div which can be modified by user. This action updates redux object containing data which will be passed to backend on submit. Since it has some sanitization logic regarding content of div, seems like it has got a delay to update redux object.
Therefore, when you click on save button, it fires an action "UPDATE_DATA", which sends old data to backend, which was in redux before modification of div.
The problem is that, I need somehow to check that "MODIFY_FIELD" action has finished and only then fire action "UPDATE_DATA".
Approach .then() does not make a sense here since I am not gonna fire "UPDATE_DATA" each time then "MODIFY_FIELD" happens.
I have a Calendar component which, when rendered with a certain prop called LoadOnMount needs to call the server to load a set of flights.
The problem is that I update the calendar by listening to the CalendarStore's Events.UPDATE event, which is triggered by the UPDATE_CALENDAR action dispatched by my Dispatcher, and I load the set of flights using another action called LOAD_FLIGHT_LIST. So when I invoke this new action from the Calendar component's ComponentDidMount function I get the cannot dispatch in the middle of a dispatch error.
Any way to handle these sorts of dependencies? (The calendar is also fetched from the server)
You have two issues that I can identify:
The first is that you are trying to get the dispatcher to dispatch during a dispatch. That's not the way you should be doing it.
The second is that you seem to be performing AJAX/async calls from inside your dispatch handler. I don't want to say that you should never do that, but that does not seem to be necessary in your application.
Here's a link to another stack overflow question that I think is similar: https://stackoverflow.com/a/23637463/2152216
The difference is that the asker is trying to perform an Ajax call from within his dispatch handler, while you seem to be trying to dispatch an event that will in turn trigger an ajax call during the event's handling.
What you can do is create an action that asynchronously loads the flight list, then dispatch the FLIGHT_LIST_LOADED action afterwards passing it the fetched flight list. Your store should handle this action and broadcast a change event for all the component observers.
I hope you understand what I'm talking about. If you think I misunderstood your problem, let me know.
I've had something bothering me for the past couple of days and I can't seem to come up with a solution that I like. I'm using refluxjs, but I think its applicable to vanilla flux as well.
So, say I have a React ComponentOne that calls a flux action to post some form data to an API to create a Thing.
My store fires a "ok, a Thing is POSTing" event, and then in a bit fires a "ok, a Thing was created" event.
How is my ComponentOne supposed to disambiguate these events? ComponentTwo could have called the same action and we don't know which Thing-POSTed event corresponds to which component.
Maybe ComponentOne's data results in a failure event, whilst ComponentTwo results in a completed event...we've got two events, both of which are plausible events for both components to expect and no obvious way to tell which is which.
You can maintain the state of API data changes inside respective Store like isLoading, isLoaded and optional time stamp. Then inside View onChange event get the current state from Store and update respective View with current state.
see related solution - Calling other action on the basis of results of other action in React JS
I'm trying to wrap my head around Facebook's Flux...
Say I have an app with a side menu that can be hidden and shown via a button in the header.
My header is one component, my side menu is another component.
Currently my Header component just sets a class on the HTML div side menu element which gets animated to hidden by CSS.
What's the general idea here?
ReactJs doesn't really care about how it gets its data (how it's data is getting passed in or how that data should be handled across the web application). That's where Flux comes in, it creates a functional approach on how data is handled. Data-flow is essentially:
Action -> Data Store -> Component
Mutation of data happen through calling Actions. The Data Stores themselves have to listen on the actions and mutate the data within the store. This keeps the data structure and logic flat.
In your case, your dataflow would probably look something like this:
Header --> User Click --> Fires action --> Updates store --> Side menu listening and responding to that store change.
Your case is a simple example which you probably don't really need Flux. I think it's easier if you have a parent component that maintains the view state logic, and use props/callbacks for the 2 children components (side menu and header). But a more advanced example that you need to make ajax calls and maintain session, Flux would become useful. Like if you have a Login Component, and you want to show different side-menu options and header options depending on user:
Login Component --> User Logins --> Calls Action #signIn --> Showing Loading State
--> Dispatcher handles action (make api call to authenticate user and load user data)
On success (for the api call), alert sessionStore, and populate store with data
On error, maybe fire another action that says login failed or something
SessionStore ---> Header Component (Listens to Store) --> Update view based on store information
---> Side Menu Component (Listens to Store) --> Update
speaking more general:
flux is a software architecture for a unidirectional Dataflow. It's Chain is Action -> Delegation -> Store -> View... The action - for example a Button Click - gets delegated to stores where your applicationlogic and data is kept... here your action and data will be changed and processed. The store eventually emits an event which views (for example react components) previously registered on with a callback. In this callback you can GET your data from your stores. It is important to mention that you can only access the stores READ-Only.
So for your case... if you want component A to affect component B you will have to register component B to the store eventEmitter and GET the desired data from the store. Once component a triggers an action it gets delegated to the store, your functions are performed and eventually the event gets thrown that starts component B's callback.
Hope this got clear enough... its way cooler with some nice drawings.