我正在构建一个 React 应用程序,它利用上下文来存储一些全局变量和函数。
我的上下文文件有一些状态值,这些状态值在一些初始 api 函数触发后都会更新:
export const CurrentUserAppProvider = ({
children,
}) => {
const [referral, setReferral] = useState()
function getReferralById(referralMasterId: string) {
return referralAxios
.get(`/api/Referral`)
.then(function (response) {
setReferral(response.data)
})
.catch(function (error) {
})
}
const appContext = {
referral,
}
return (
<AppContext.Provider value={appContext}>{children}</AppContext.Provider>
)
}
在我的主文件中,我想使用上下文
referral
值(当它们可用时)更新减速器的值。
export const ReferralDetails: React.FC<{}> = ({}) => {
const {
referral,
} = useContext(AppContext)
const [referralData, setReferralData] = useReducer(referralReducer, {
currentAssigneeDisplayName: referral?.currentAssigneeDisplayName || '',
currentAssigneeEmail: referral?.currentAssigneeEmail || '',
currentAssigneeGRNID: referral?.currentAssigneeGRNID || '',
referralMasterId: referral?.referralMasterID || null,
reasonTypeId: referral?.reasonTypeID || '',
referralTypeId: referral?.referralTypeID || '',
riskDescription: referral?.riskDescription || '',
statusTypeId: referral?.statusTypeID || 1,
})
function referralReducer(
state: ReferralReducer,
event: { name: string; value: string | number | unknown }
) {
return { ...state, [event.name]: event.value }
}
上面的代码没有将我的减速器设置为这些上下文值。我认为这是因为在设置上下文值之前就设置了值。
我认为我可以通过运行
useEffect
函数来在 referral
数据可用时运行一些代码来解决问题。但是我想不出一个干净的函数来更新所有值。
下面的代码可以工作,但它很难看并且感觉多余:
useEffect(() => {
setReferralData({
name: 'actionStepId',
value: referral?.actionStepID || 1,
})
setReferralData({
name: 'comment',
value: referral?.comment || '',
})
setReferralData({
name: 'currentAssigneeDisplayName',
value: referral?.currentAssigneeDisplayName || '',
})
setReferralData({
name: 'currentAssigneeEmail',
value: referral?.currentAssigneeEmail || '',
})
setReferralData({
name: 'currentAssigneeGRNID',
value: referral?.currentAssigneeGRNID || '',
})
setReferralData({
name: 'referralMasterId',
value: referral?.referralMasterID || '',
})
setReferralData({
name: 'reasonTypeId',
value: referral?.reasonTypeID || '',
})
setReferralData({
name: 'referralTypeId',
value: referral?.referralTypeID || '',
})
setReferralData({
name: 'riskDescription',
value: referral?.riskDescription || '',
})
setReferralData({
name: 'statusTypeId',
value: referral?.statusTypeID || '',
})
}, [ referral])
这可能有点令人惊讶,但是
useReducer
钩子的用途与 Redux 的工作方式非常相似,在你有状态和分派 actions 的情况下,这些操作是在减速器情况下处理的。
基本示例:
const reducerFunction = (state, action) => {
switch(action.type) {
case "action1":
return {
...state,
// apply action 1 changes
};
case "action2":
return {
...state,
// apply action 2 changes
};
... other cases ...
default:
return state;
}
};
const [state, dispatch] = useReducer(reducerFunction, initialState);
...
dispatch({
type: "action1",
payload: { ... some payload value ... }
});
您基本上使用
useReducer
就像它是
useState
钩子一样,并且通过实现减速器的方式,您一次只能更新一个状态属性。更新您的减速器函数,以便它可以应用正确的更新模式,即处理特定操作。interface ReferralEvent {
name: string;
value: string | number | unknown;
}
function referralReducer(
state: ReferralReducer,
action: { type: string; payload: unknown },
) {
switch(action.type) {
case "setReferralData":
return {
...action.payload
};
case "setReferralProperty":
const { name, value } = action.payload as ReferralEvent;
return {
...state,
[name]: value
};
case "setReferralProperties":
return {
...state,
...action.payload
};
... other cases ...
default:
return state;
}
}
export const ReferralDetails = () => {
const { referral } = useContext(AppContext);
const [referralData, dispatch] = useReducer(referralReducer, referral);
useEffect(() => {
dispatch({
type: "setReferralData",
payload: referral,
});
}, [referral]);
...
};