使用上下文值更新React减速器值

问题描述 投票:0回答:1

我正在构建一个 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])
reactjs react-hooks react-context
1个回答
0
投票

这可能有点令人惊讶,但是

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]);

  ...

};

© www.soinside.com 2019 - 2024. All rights reserved.