reactjs - 使用 formik、yup 和 axios 去抖动
问题描述
尝试对 api 调用进行去抖动以检查给定的电子邮件地址是否已被占用。
这是错误的逻辑。
const request = email => {
return Axios.get(
'http://localhost:4000/api/v1/users/precheck?user[email]=' + email,
).then(response => {
return response.data.precheck == 'ok';
});
};
const checkEmail = _.debounce(request, 1000);
export const Signup = withFormik({
mapPropsToValues: () => ({ email: '' }),
validationSchema: object().shape({
email: string()
.email('Invalid email address')
.required('Email is required!')
.test('email', 'email already taken', email => {
_.debounce(checkEmail(email));
}),
}),
...
})(InnerForm);
这将产生
createValidation.js:63 Uncaught (in promise) ValidationError {name: "ValidationError", value: "aaa", path: "email", type: undefined, errors: Array(1), …}
Promise.then (async)
validate @ createValidation.js:107
(anonymous) @ mixed.js:245
(anonymous) @ mixed.js:244
Promise.then (async)
_validate @ mixed.js:238
validate @ mixed.js:256
(anonymous) @ object.js:202
(anonymous) @ object.js:188
Promise.then (async)
_validate @ object.js:179
validate @ mixed.js:256
validateYupSchema @ formik.esm.js:547
(anonymous) @ formik.esm.js:205
Formik._this.runValidationSchema @ formik.esm.js:200
Formik._this.runValidations @ formik.esm.js:217
executeChange @ formik.esm.js:257
Formik._this.handleChange @ formik.esm.js:269
callCallback @ react-dom.development.js:100
invokeGuardedCallbackDev @ react-dom.development.js:138
invokeGuardedCallback @ react-dom.development.js:187
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js:201
executeDispatch @ react-dom.development.js:461
executeDispatchesInOrder @ react-dom.development.js:483
executeDispatchesAndRelease @ react-dom.development.js:581
executeDispatchesAndReleaseTopLevel @ react-dom.development.js:592
forEachAccumulated @ react-dom.development.js:560
runEventsInBatch @ react-dom.development.js:723
runExtractedEventsInBatch @ react-dom.development.js:732
handleTopLevel @ react-dom.development.js:4476
batchedUpdates$1 @ react-dom.development.js:16659
batchedUpdates @ react-dom.development.js:2131
dispatchEvent @ react-dom.development.js:4555
interactiveUpdates$1 @ react-dom.development.js:16714
interactiveUpdates @ react-dom.development.js:2150
dispatchInteractiveEvent @ react-dom.development.js:4532
formik.esm.js:529 Uncaught (in promise) TypeError: Cannot read property 'length' of undefined
at yupToFormErrors (formik.esm.js:529)
at formik.esm.js:208
yupToFormErrors @ formik.esm.js:529
(anonymous) @ formik.esm.js:208
Promise.then (async)
(anonymous) @ formik.esm.js:205
Formik._this.runValidationSchema @ formik.esm.js:200
Formik._this.runValidations @ formik.esm.js:217
executeChange @ formik.esm.js:257
Formik._this.handleChange @ formik.esm.js:269
callCallback @ react-dom.development.js:100
invokeGuardedCallbackDev @ react-dom.development.js:138
invokeGuardedCallback @ react-dom.development.js:187
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js:201
executeDispatch @ react-dom.development.js:461
executeDispatchesInOrder @ react-dom.development.js:483
executeDispatchesAndRelease @ react-dom.development.js:581
executeDispatchesAndReleaseTopLevel @ react-dom.development.js:592
forEachAccumulated @ react-dom.development.js:560
runEventsInBatch @ react-dom.development.js:723
runExtractedEventsInBatch @ react-dom.development.js:732
handleTopLevel @ react-dom.development.js:4476
batchedUpdates$1 @ react-dom.development.js:16659
batchedUpdates @ react-dom.development.js:2131
dispatchEvent @ react-dom.development.js:4555
interactiveUpdates$1 @ react-dom.development.js:16714
interactiveUpdates @ react-dom.development.js:2150
dispatchInteractiveEvent @ react-dom.development.js:4532
解决方案
对于仍在寻找的人,这是我设法做到的:
export function asyncDebounce(func: any, wait: any): (...args: any[]) => Promise<unknown> {
const debounced: DebouncedFunc<(resolve: any, reject: any, bindSelf: any, args: any) => Promise<void>> =
debounce(async (resolve: any, reject: any, bindSelf: any, args: any) => {
try {
const result: any = await func.bind(bindSelf)(...args);
resolve(result);
} catch (error) {
reject(error);
}
}, wait);
// This is the function that will be bound by the caller, so it must contain the `function` keyword.
function returnFunc(...args: any[]) {
return new Promise((resolve, reject) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line no-invalid-this
debounced(resolve, reject, this, args);
});
}
return returnFunc;
}
但是现在你必须使用 ref 和 raw apollo 查询:
const apolloClient: ApolloClient<any> = useApolloClient();
const emailAddressDebounce: React.MutableRefObject<(...args: any[]) => Promise<unknown>> =
useRef(asyncDebounce(apolloClient.query, 350));
email: Yup.string()
.email('Invalid email address')
.required('Required')
.test(
'email-backend-validation',
'Email already in use',
async (email: string | undefined) => {
if (!email) {
return true;
}
const result: EmailTakenQueryData = await emailAddressDebounce.current({
query: emailAddressTakenQuery,
variables: { email },
}) as unknown as EmailTakenQueryData;
if (result?.data?.emailAddressTaken) {
return !result?.data?.emailAddressTaken;
}
return true;
}),
这有效:)
推荐阅读
- asp.net-core - 如何在评估 Razor 标签的 Razor 页面中使用内联条件
- css - Internet Explorer 10 中的导航和滑块会发生什么情况?
- bison - 为什么 Bison 总是给我“第 x 行附近的语法错误”?
- css - 如何开始选择元素与表单中的标签对齐
- sql - 首次下订单时获取日期和唯一客户数
- python-3.x - 将元素插入二维列表
- python-3.x - Python while循环不等待用户输入
- node.js - 如何使用 Mongoose 在 NodeJS 中进行密码验证
- r - if ((pValue < pFilter) & (coxP < pFilter) & (fiveYearsDiff > 中的错误:需要 TRUE/FALSE 的缺失值
- javascript - 有没有办法从 wordpress api 获取待处理的评论/帖子?