I'm writing a restful redux/react app.
My desired output is such.
INPUT_CHANGE-->
(state = {valid: false})->REDUCER->(state = {valid: true})-->
AJAX CALL
From the redux documentation, async javacript is supposed to be called from the action creator, but I don't understand how to get to the action creator once the state changes from valid:false to valid:true.
Since this is a react app, I could change a hidden input called valid, which has an onChange action creator attached to it, but this seems like an unneccessary extra step. Any ideas?
My general preference is to have the action creators handle all async operations. So the validation operation in this question is comparable to the shouldFetchPosts function in http://rackt.org/redux/docs/advanced/AsyncActions.html
The action creator would then be something like inputChangeAndSubmitIfValid which corresponds to that file's fetchIfNeeded action creator.
On very rare occasions I implement an observer for catching store changes, but I always try to find a better action oriented way first.
Related
I want to perform an action based to the result of an asynchronous NGXS action.
In a Angular frontend app I'm using NGXS for state management. Some of the actions involve talking to a backend via REST calls. Those actions are implemented as asynchronous actions, with the reducer functions in my state classes returning an Observable.
What I'm looking for is a way to get hands on the result of the backend call, to be able to perform some action.
One use case I'm trying to implement is navigation to just created objects: Business objects are created in the frontend (Angular) app with a couple of domain properties. They get persisted in the backend, and as a result an ID for this object is created and returned to the frontend, and incorporated into the NGXS store. As a direct response to this, I'd like to navigate to a detail view for the new object. To do so, I need
(a) the information that the call has been returned successful, and
(b) the answer from the backend (the ID in this case).
Another slightly more complicated use case is the assignment of a number of tags to an business object. The tags are entities by themselfes, and have an ID each. In the UI, the user can either pick existing or add new tags. Either way, multiple tags can be added in a single step in the UI, which means I have to
call the backend for each new tag to create the ID
after all missing tags are created, update the business object with the list of tag IDs
In general, there are use cases in the frontend that depend on the result of a backend call, and there is no clean way to find this result in the store (although it's in there)
I know I can subscribe to the Observable returned from the store's dispatch method (as shown in asynchronous actions).
I also know about action handlers. In both cases I can attach code to the event of an action finished, but neither option enables me to get the result of the backend call. In the fist case, the Observable carries the whole store, while in the latter case I get the original Action, which is unfortunately missing the essential information (the ID).
The part you're missing here are selectors. Dispatching actions is not supposed to give you back a result. The only purpose of the Observable returned by store.dispatch() is to tell you when the action's handlers are done.
To get to the data returned by your calls to the backend, you have to patch the state inside your action handler. And then, outside of your state, you can access the data using store.select() or store.selectSnapshot() depending on what you need. Your state class should look somewhat like this (untested):
#State()
export class SampleState {
#Selector(SampleState)
sampleSelector(state) {
return state.sampleObject;
}
#Action(SampleAction)
sampleAction(ctx: StateContext<any>, action: sampleAction) {
return sampleBackendCall(/* ... */).pipe(
tap((result) => {
ctx.patchState({ sampleObject: result });
})
);
}
}
Now you can access this result where ever you need using the Store. For the use case of navigating to an element after its creation, you can combine a subscription to store.dispatch() with a store.selectSnapshot() like this:
store.dispatch(new SampleAction()).subscribe(() => {
navigateTo(store.selectSnapshot(SampleState.sampleSelector));
});
Note that in this easy case a selectSnapshot is perfectly fine, as we only want to get the value we just finished writing into the state. In most cases though, you will want to use store.select() or the #Select() decorator because they return Observables which enable you to also correctly display changes in your state.
That said, I'd like to add that if saving data inside the state is not necessary for you at all, then probably NGXS is the wrong library for you in the first place and you could as well just use an ordinary angular service directly returning the result of the backend call, like suggested in the comments.
I am very new to redux and redux-observable so I would like to ask for some advice.
I am using redux-observable with rxjs to handle all my side effects which works very well.
I am using redux-form to handle form input and form validation that works also very well.
My problem is to integrate them together. My understanding is that redux-observable runs parallel to my ordinary actions creators so the action I invoke when I submit the form will always return without an error and my parallel running observable will yield a different action down the line if there was any issue with the submittion so I am not sure how I could handle it properly.
I found the following library. https://github.com/salsita/redux-form-actions
that looks like using a HOC to wrap the action with a promise. I am just wondering if that is the right way to go about it and how it works.
Can someone from the redux-form community check it out and let me know if it looks good. I do not have enough knowledge to make a call at this point as I wrote my first form today and I do not with to go down the wrong path.
Also an explanation how this works would be gratelly appreciated too / if there is a better approach.
I appreciate any comment or notes!
Thanks a lot !
The gist is, within onSubmit, pass a Promise's resolve/reject functions to a dispatched action. await on that promise. then, in your epic, call resolve/reject as needed to resume onSubmit's flow.
here's my PR explaining how it works, with a runnable example: https://github.com/redux-observable/redux-observable/pull/490
I like to re-trigger validations after the form has mounted. Let's assume I like to run the validations each time I click a button named 'validate inputs'.
How to do this?
Related questions:
How to run validation on a slice of a redux-form FieldArray state
Is there a way in Redux Forms to make a form validate from code?
Manual redux-form validation is an oft requested feature, that does not seem to be provided at the moment.
My personal workaround is to trigger this.props.change('_validationHack', Date.now()) in the reduxForm-wrapped component and then remove values._validationHack in the onSubmit method before sending the values to the server.
It's not pretty, but seems to work without exception.
According to 28/11/2018:
https://redux-form.com/6.2.1/docs/api/actioncreators.md/
There are actions that you can dispatch for making changes to your form and triggering the validation method.
If you trigger change/touch actions it should execute the validate function.
This worked for me:
import { touch, stopAsyncValidation } from 'redux-form';
//...
yield put(stopAsyncValidation('CallForm', { mdn: mdn.error_message }));
yield put(touch('CallForm', 'mdn'));
clue from https://stackoverflow.com/a/51065315/588759
clue about touch https://github.com/redux-form/redux-form/issues/3992#issuecomment-399411329
working example https://github.com/zobroj/ab-web/blob/ea4fccb68b4f3a2f747f47d23624bc69631782ed/app/containers/RegisterPage/sagas.js#L62
found with https://github.com/search?l=JavaScript&q=%22yield+put%28touch%28%22&type=Code
The sync validation is run on every render, so "triggering it" doesn't really have much meaning.
If you would like to use async validation, there is a this.props.asyncValidate() function that you can call to trigger it.
OR, if you prefer submit validation, you could just submit the form.
this question is about where to put validation of an form element in redux. I feeeeel as though I should have an onValueChange event that dispatches an action to the reducer that validates and updates both the value ( invalid or valid as it may be ) as well as the "isValid" property on state so that that element can then display an error.
Conversely, I could do the validation in the action, and if it fails just dispatch a failure action instead.
One note is that i do prefer the anonymous function nomenclature to extending the react.component.
I guess I should change then name of this to where is the proper place to put validation in the redux flow.
Keep the validation in your component. I hear a lot of "keep all state in redux", but I try to only keep what I absolutely need in redux. Use component state with a error property and if your validation fails set the state on the error property. As well, redux forms: http://redux-form.com/4.2.0/#/?_k=mhjui4 is a good library for simple and complex forms.
The specific case I've got in mind is as follows: an AjaxFormComponentUpdatingBehavior("onchange") is added to a TextField in a form. The behavior verifies the text for certain conditions (either the model object or the form component model, doesn't matter), based on which it might display a message (or hide it, if it has already been shown).
The problem is, there are also validators added to the TextField. One of the possible (and likely) scenarios consists of the user typing in, first, a value that causes the message to be displayed by the AJAX request. If, then, he/she types in a value that doesn't pass validation, the message should disappear, but it does not.
Apparently, either the onUpdate() method for the AJAX behavior is not called at all, or I am failing in my attempts to insert a check for non-validated entries (I have tried to test for both null values and empty strings, to no avail; I have no idea what exactly Wicket's validators do to models when data is invalid).
I am wondering if someone who actually understands validators (or AJAX, actually) has any ideas on where the problem could be.
I can post edit and post code if someone tells me this is not a general issue tying validators and AJAX, but most likely a programming mistake. I still believe the former and thus I'll refrain from posting code sections, in order to keep the discussion on an API/theoretical frame.
Thanks.
When using an AjaxFormComponentUpdatingBehavior, if any of the IValidators fail their validation, onError() will be called instead of onUpdate(). Wicket will effectively prevent invalid user input from reaching the IModels in your components, so the component's ModelObject will not be changed at all. The invalid input will probably remain available by means of getInput()/getConvertedInput() (not sure if it will in an AJAX scenario, it sure is in a traditional form submission).
However, take into account that IFormValidators are not executed when using this mechanism. If you've got any, you might be interested in overriding getUpdateModel() so that AjaxFormComponentUpdatingBehavior will not bring maybe-invalid user input into your IModels, and set modelobjects manually when you're certain user input is valid.
Regarding your specific case, you could perform all the required logic in onError() (or rely on Models that will grab data from somewhere else), and just add the components that need refreshing to the AjaxRequestTarget. This is probably what's missing in your scenario.