Closed betancourtl closed 6 years ago
I ended up submitting the form inside the onSuccess hook, and it is showing up the server errors correctly now. Anyone knows is this is the correct way to handle server errors after an API call?
import MobxReactForm from 'mobx-react-form';
import validatorjs from 'validatorjs';
import { authenticate } from "../api/auth";
const plugins = { dvr: validatorjs };
const fields = [
{
name: 'email',
label: 'Email',
placeholder: 'Insert Email',
rules: 'required|email|string|between:5,25',
value: 'webdeveloperpr@gmail.com'
},
{
name: 'password',
label: 'Password',
placeholder: 'Insert Password',
rules: 'required|string|between:5,25',
value: '123qweQWE',
type: 'text'
}
];
const hooks = {
onSuccess(form) {
// I want to handle success here
authenticate({
email: form.$('email').value,
password: form.$('password').value,
})
.then(({ user, token }) => {
this.rootStore.session.startSession(user, token);
})
.catch(err => {
if (err.email) {
form.validate('email')
.then(({ isValid }) => {
form.$('email').invalidate(err.email);
});
}
if (err.password) {
form.validate('password')
.then(({ isValid }) => {
form.$('password').invalidate(err.password);
});
}
});
},
onError(form) {
// Not really sure why I would handle anything in here ¯\_(ツ)_/¯
console.log('All form errors', form.errors());
}
};
class LoginForm extends MobxReactForm {
static storeName = 'loginForm';
constructor() {
super({ fields }, { plugins, hooks });
}
}
export default LoginForm;
const storeName = LoginForm.storeName;
export {
storeName,
}
Now im running into issues. The async validation works fine and errors show up but then the sync validation kicks in and the async errors dissappear...... How do I preserve the async errors until the next time the user submits?
Ok I ended up setting the errors using a timeout to bypass the issue. This feels so hacky.
import MobxReactForm from 'mobx-react-form';
import validatorjs from 'validatorjs';
import { authenticate } from "../api/auth";
const plugins = { dvr: validatorjs };
const fields = [
{
name: 'email',
label: 'Email',
placeholder: 'Insert Email',
rules: 'required|string|between:5,40|email',
value: 'webdeveloperpr@gmail.com'
},
{
name: 'password',
label: 'Password',
placeholder: 'Insert Password',
rules: 'required|string|between:5,25',
value: '123qweQWE',
type: 'text'
}
];
const hooks = {
onSuccess(form) {
// I want to handle success here
authenticate({
email: form.$('email').value,
password: form.$('password').value,
})
.then(({ user, token }) => {
this.rootStore.session.startSession(user, token);
})
.catch(err => {
// Prevents the text input's onBlur event from removing the async errors. The unblur event triggers a validation check.
setTimeout(() => {
if (err.email) {
form.validate('email')
.then(({ isValid }) => {
console.log('isValid', isValid);
form.$('email').invalidate(err.email);
});
}
if (err.password) {
form.validate('password')
.then(({ isValid }) => {
form.$('password').invalidate(err.password);
});
}
}, 250);
});
},
onError(form) {
// I want to handle errors here
console.log('All form errors', form.errors());
}
};
class LoginForm extends MobxReactForm {
static storeName = 'loginForm';
constructor() {
super({ fields }, { plugins, hooks });
}
}
export default LoginForm;
const storeName = LoginForm.storeName;
export {
storeName,
}
I had the same problem, my code is nearly identical to @webdeveloperpr, but I solved it storing the error message in a store and clearing it up on componentWillMount:
class MobxLoginForm extends MobxReactForm {
...
hooks() {
return {
onSuccess(form) {
const { email, password } = form.values();
this.session.logIn(
email, password
).then((response) => {
if (!response.success && response.payload.length > 0) {
form.invalidate();
this.session.setLoginError(response.payload[0]); // set the error message in the store
if (this.handleError != null) {
this.handleError();
}
} else if (this.handleSuccess != null) {
this.handleSuccess();
}
});
},
// other hooks here
and in my component that is rendering the form:
@inject('session') @observer
class LoginForm extends React.Component {
componentWillMount() {
this.props.session.setLoginError(null);
}
render() {
...
{session.loginError ? <p className="error">{session.loginError}</p>}
This works quite well, but it would be great to have a better way.
The onSuccess
hook should return a promise
to work.
seems like there's a bug here. @michalpleszczynski, could you take a look at this?
Steps to reproduce:
Expected outcome Email field is invalidated with "whatever reason"
Actual outcome Email field briefly flashes invalidated state and then becomes validated
On a side note, focus()
doesn't appear to work consistently for fields. I tried forcing focus on the field before/after invalidate()
so the async validation wouldn't clear my error but had mixed results.
In the end, I used these options with success:
const options = {
validateOnBlur: false,
validateOnChange: true
}
@webdeveloperpr
I'm looking at the docs it's not clear to me where to make an API call when submitting the form. I also need to find out how to show server errors for each field.
I tried adding an onSubmit function to the class and it gets called but the hooks do not work.
Store
Component