[英]How to handle async update onUpdate of each field and keep ids using redux-form and redux-observable
我在我的應用程序中使用redux-observable,並嘗試為我的情況添加redux-form(異步驗證,跟蹤所有操作),在這種情況下,我需要制作一個在每次數據更改時都進行異步調用的表單。 我不想手動提交表單並提出集中提交請求(如官方示例所做的那樣)。
考慮到redux-form在每個字段@@redux-form/CHANGE
上都派發一個@@redux-form/CHANGE
動作,因此很容易利用redux-observable並“監聽”該動作並基於其進行一些限制,取消,重試等在這些動作上。 每個異步調用(一旦將其保存到db中)將返回特定字段的ID。
根據以下代碼示例,取自redux-form-redux-observable
const registerEpic = (action$, { getState, dispatch }) =>
action$.ofType('REQUEST_SUBMIT')
.do(dispatch(startSubmit('contact')))
.mergeMap(action =>
fromPromise(submitToServer(action.data))
.map(response => {
console.log(response);
dispatch(stopSubmit('contact', response.errors || {}));
if (response.errors) {
return {
type: 'REQUEST_FAILED',
errors: response.errors,
}
} else {
return {
type: 'REQUEST_SUCCESSFUL'
}
}
})
);
我嘗試處理從redux-form分派的操作。 調度@@redux-form/CHANGE
,它將進行服務器調用,當此調用解析后,我將從服務器獲取字段ID。 我可能需要將其添加到表單的存儲中,並在需要對服務器進行此特定字段的DELETE請求后,將其用作“將來使用”的參考。
我認為解決此問題的方法是從服務器解析完數據后調度redux-form change
操作,但這再次觸發@@redux-form/CHANGE
,並且表單(顯然)在我進入無限循環之后繼續收聽@@redux-form/CHANGE
操作。
const updateEpic = (action$, { getState, dispatch }) =>
action$.ofType('@@redux-form/CHANGE')
.debounceTime(1000)
.do(x => console.log(x))
.do(x => console.log(getState().form.contact.values[x.meta.field]))
.mergeMap(action =>
fromPromise(submitToServer(xxx))
.map(response => {
dispatch(change('contact', 'firstName', 'test'));
})
);
因此,我在這里遇到了一些困難的案例:
我如何將服務器返回的ID添加到商店(以備將來使用)
如何通過引入另一種方式來處理我的案件來巧妙地避免這種無限期
最后,我想知道redux-observable和redux-form的組合是否適合我的需求。
謝謝
我最終設法通過使用reducer.plugin()調度了一個新操作,並將從服務器返回的數據應用於每個字段的meta
數據,從而解決了此問題。
下面是一個簡單的例子
const updateEpic = (action$, { getState, dispatch }) =>
action$.ofType('@@redux-form/CHANGE')
.debounceTime(1000)
.do(x => console.log(x))
.do(x => console.log(getState().form.contact.values[x.meta.field]))
.mergeMap(action =>
fromPromise(submitToServer(xxx))
.map(response => {
return {
action: 'CUSTOM_ACTION',
payload: {
id: response.id,
meta: action.meta // <-- this is the initial action that helps you to know which is the field you need to update
}
}
})
);
對於減速器側
myReducer(state = {}, action) {
switch (action.type) {
case 'CUSTOM_ACTION':
return merge({}, state, {
[action.payload.meta.form]: {
fields: {
[action.payload.meta.field]: {
id: action.payload.id
}
}
}
})
break;
default:
return state
}
}
最后,您可以從React Component中的meta
獲取id
const renderField = ({ type, label, input, meta: { touched, error, warning, id = undefined } }) => (
<div className="input-row">
<pre>{id}</pre>
<label>{label}</label>
<input {...input} type={type}/>
{touched && error &&
<span className="error">{error}</span>}
{touched && warning &&
<span className="warning">{warning}</span>}
</div>
);
如果其他人有更好的解決方案,我想告訴我們。 我認為這個問題是封閉的。
@stelioschar,我對其進行了研究,發現您可以采用這種方法,我認為它非常有效,我將代碼留在這里,如果其他人對此有所不同,請分享。
當用戶鍵入時,我正在驗證,當它達到6個字母時,我向服務器發送了一個請求:
export const validateUserNameEpic = function (action$, store) {
return action$.ofType('@@redux-form/CHANGE')
.filter(action => action.meta.field === "userName")
.filter(action => (!utility.validation.lengthMin6(action.payload) && !utility.validation.userName(action.payload)))
.debounceTime(500)
.mergeMap(action =>
Observable.ajax({
url: `${apiUrl}/auth/validations/v1`,
method: 'POST',
body: JSON.stringify({
type: 'user-name',
value: action.payload
}),
headers: {
'Content-Type': 'text/plain'
},
crossDomain: true
})
.map(data => {
const previousErrors = store.getState().form.signUp.asyncErrors;
if (data.response === 'true' || data.response === true){
return {
type: "@@redux-form/STOP_ASYNC_VALIDATION",
meta:{
field: "userName",
form: "signUp",
touch: true
},
error: true,
payload: Object.assign({}, previousErrors, { userName : "b591d5f.0450d1b.76ae7b1.d" })
}
} else {
return {
type: "@@redux-form/STOP_ASYNC_VALIDATION",
meta:{
field: "userName",
form: "signUp",
touch: true
},
error: false,
payload: previousErrors
}
}
})
.startWith({
type: "@@redux-form/START_ASYNC_VALIDATION",
meta:{
field: "userName",
form: "signUp"
}
})
.startWith({
type: "@@redux-form/BLUR",
meta:{
field: "userName",
form: "signUp",
touch: true
}
})
.catch(error => Observable.of({
type: "@@redux-form/STOP_ASYNC_VALIDATION",
meta:{
field: "userName",
form: "signUp"
}
}))
)
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.