Flux calling actions with arguments managed in store - javascript

Say I have an action someAction(params) that takes params which is managed in a store paramsStore:
paramsStore.listen(function(params) {
someAction(params)
})
It seems that I can't just call this in my view because apparently this goes against the Flux way of doing things (actions shouldn't be called within store listeners).
The reason I have someAction inside the store listener, is because I want it to be called every time the paramsStore is modified. How can I achieved this without resorting to the 'unpattern' of calling actions within stores listener?

The right "flux way" of doing it would be to call the someAction(params) wherever information is dispatched to paramsStore.
Understanding what someAction does will give more clarity. Does it really need to be an action? If you're just doing some manipulation in the store data, you could have it as a local method in the paramStore.

While I am new to flux as well I could offer a suggestion. State that is needed to determine the outcome of an action that is held by Store A could be attached to a get method. This state can be retrieved by a View with a getter. When the action is called this state can be sent as a parameter. If something needs to be async it can now be done here (ajax call or something else) based on what the state is. Either the result of this or a promise object can then be used to trigger an action which is passed to the dispatcher. The dispatcher sends the result or promise to the store. The store then updates its state and the process repeats as necessary (when initial action is triggered).
I think a little more detail of what exactly you need would help actually. I do believe listening for for an action and triggering another action inside the store doesn't coincide with flux. I do think there is likely a way to accomplish the actual result you want using flux but without more detail this is the best I could come up with. Also, in reality you can implement anything you want. Flux is just a model and by extension a self imposed constraint to help with structure.

If you are using Flux as is, you could refer to the original image of the whole architecture at https://github.com/facebook/flux.
As you can see not only views could create actions. There are also Web API Utils which could create ones. Generally speaking not only API utils can do this. It's totally okey to create actions in order to start some behaviour according to outside world, some services or something else.
But in your case you are trying to create an action on some store update listener. As far as I can understand this would result in some changes in one or few other stores. In this case you probably don't need to create an action in the listener, but rather create some relations between your stores with waitFor API. Here is a link with detailed information: http://facebook.github.io/flux/docs/todo-list.html#adding-dependency-management-to-the-dispatcher.

Related

Incrementing variable in action creator

I was recently watching Dan Abramov redux series and one episode got me really curios. In this episode - Redux: Extracting Action Creators, timecode: 00:32~1:32 he's making action creator as a separate function (like it would normally look in the typical redux application) because:
... However, what if another component wants to dispatch the add todo
action? It would need to have the access to next todo ID somehow
But is that actually making any sense? In that particular example, nextTodoId variable (which is always incrementing) is available to all components inside that jsbin even if we don't extract action creator into a function.
Even if we'll imagine that it will be in a separate file (action creator), on each import that variable will be equal to the initial value (0) which breaks it's uniqueness concept.
So, what does he meant by that? How is that approach (of making action creators as a separate functions) will guarantee us the acccess to that next todo id variable?
You're focusing on the wrong aspect. It's a fair enough point that this is a terrible way to store "current ID", but that isn't the purpose of the refactor he is showing.
The real purpose is that Components should be as agnostic about their context as possible. A Component trying to "addTodo" really shouldn't be concerned with "what is the current max todo ID?".
In contrast, the actionCreator is concerned with this aspect. It takes in data from the components and is then responsible for translating it to a dispatchable call that has real value.

Where to put non-ui logic in react/redux app?

I'm writing a react/redux app that has a Job object that fires Events from time to time. On these Events the user is expected to react. I can easily write the React component that shows such a job or events, but don't know where to put the logic when
the user is not on the Job page
and an Event happens
and I would like to pop up a notification
Of course, once I get access to the store, I can create the notification too.
Shall I handle such logic in a React container that render() nothing?
Or handle it with vanilla JS when I load a Job data?
Or to handle it in the reducer when the data is stored? (probably not recommended)
My problem with the option two is that I don't know how to access the redux store from a totally ad-hoc code, as my store is not a global object.
What do you recommend?
Generally speaking, the two places that you'd put code that needs to access the store (for either dispatching or receiving state updates) is in middleware or a connected component. If you specifically want to respond to an action coming through, then you would need to use middleware.
I actually threw together a sample timer middleware in a chat discussion a few weeks ago. I just pasted it as a gist here as an example: https://gist.github.com/markerikson/ca96a82d6fdb29388aca4052a9455431 . Illustrates the idea of doing something asynchronously in the background.
You may also want to look through the list of middlewares in my Redux addons catalog: https://github.com/markerikson/redux-ecosystem-links/blob/master/middleware.md . Numerous examples of ways to execute background-ish logic.
Finally, https://github.com/yelouafi/redux-saga (which is itself a middleware) is a fairly common lib used to do background-ish logic.

Can I send an AJAX call in React and Redux without action creators and reducers?

I have a few ajax requests that are not directly manipulating my apps state. In a react/redux application is it necessary (or is there any benefit) to dispatch an action for these ajax requests instead of just sending an ajax request directly in the component?
To simplify my scenario, I essentially have a list of objects on my redux state. I am using a form to post a new object to the database, upon successful post I am redirecting to the list page where a GET request is sent and the list is fetched and the state is updated.
The AJAX call to post a new object is not directly manipulating my state.
The team I am working with is going through the full 3 step redux async steps
ex: 'FETCH_REQUESTED', 'FETCH_SUCCESS', 'FETCH_FAIL' along with the respective reducers for all the AJAX requests and it's a big hassle to add more and the reducers don't seem to make sense.
You can absolutely send AJAX calls directly from components!
Redux is a tool for making shared state globally available to multiple components, and changed in predictable way. In any case where you don’t find this necessary, don’t do it.
Keeping AJAX calls in action creators is convenient when different components make the same API requests and then change the state in similar ways. It is also convenient if you want to avoid firing off a request when there is already some cached data available, and you want to keep such checks in a single place rather than scattered across the components.
That said Redux is only concerned with how global state is updated, and if you just need to make an AJAX request from some component, you don’t have to write an action creator or a reducer for it unless you find it convenient.
Generally saying Redux (and Flux) is what you might consider refactoring your code to when you have many complicated components; not what you should start every component with. You can use only the parts of it that you need (e.g. just the synchronous stuff), or even avoid it altogether in some cases (e.g. a collapsible panel doesn’t have to store its state in a store). Only use it when you understand the specific benefits it gives you in a particular situation, never “just in case” or because it is popular.
See also my answer to “How do dispatch a Redux action with a timeout?”
To address your specific example, you might want to use Redux for this if you use the benefits Redux gives you: maybe you dispatch an action to update the form optimistically and display the new list right away, and merge it with the fetched list when it is available so that the interaction appears instantaneous. That is the use case for async action creators. If you’re not looking at this kind of UX complexity, I’m not sure Redux is necessary at all.
Try using below link
https://github.com/sskyy/redux-task
It can help you to manage AJAX request state without those verbose actions and reducers.

React Alt Calling a store method synchronously

Developing a React/Alt application, I face a quite common scenario:
In the root component, in a button click handler, I need to check if a value in a specific store is valid before triggering an action. This value is not yet available in the state of the store since it has to be calculated.
So I have to call an action linked on the method of the store which going to calculate the value. The result will be stored in the state of the store and will be available in the listen-handler of the root component.
Unfortunately, in this case, I lose the initial context of the user action.
I'd like to synchronously calculate the value and retrieve it in the same context. Is there a way to do it? What are the best practices in such a scenario?
Thanks.
You can split your validation logic up into a separate module. On the onClick handler you can then execute this validation logic, using either store.getState() or the props of your component. The validation logic will then be separate from your component, which makes it easy to test and re-use, plus it won't clutter your component, which should be more concerned with behavior of the interface.

How to pass a prop to every component in react.js?

I'm setting up a site using react.js. the client receives a massive json through ajax that is then used to populate all the necessary fields, graphs, etc. Seeing as this json will cover pretty much all the information contained on the site, it has be accesible in almost every single component. Is there a clean way to pass it to every last component (and there are a lot of them)? Passing it the regular way to ~70 components seems dirty and inefficient.
As React's documentation states, you could have components communicate by integrate a global event system, and then subscribe to an application-data event from all your components, in componentDidMount().
This way, each time you will emit the application-data event from within the code responsible for pulling the website data, all components will receive that data. At that point, you can call setState().
Please be careful and unbind the events once a component goes "out of scope", inside componentWillUnmount().
Failing to do so will result in memory leaks, as you will have the event handler dangling, and it will be called each time you pull the website data, even if your Component's instance has been removed from the DOM.
You could also try to make your components pull data by themselves, as sending a huge JSON around, is not the best solution. I mean, each component should use the data it needs, in order to work, not the whole website data. The way I would alter this would be by parsing the JSON object and storing it for reference in a variable, on a scope that is accessible to all components, and use the event system to only notify the components that the data is ready, and each component would go to the global data object and get their data.
Example(pseudo-code):
XHR.getData
XHR.onReadyState => GlobalNameSpace.data = data
EventSystem.PUBLISH('application-data')
// component code
Component {
EventSystem.SUBSCRIBE('application-data') =>
dataNeededForInit = GlobalNameSpace.data.componentXData
}
Reference: https://facebook.github.io/react/tips/communicate-between-components.html
Context might fit the bill. It might not be particularly tidy solution but perhaps that would be a starting point for you.

Categories

Resources