redux 当使用spread运算符时,如何将undefined处理为API响应?

xxe27gdn  于 2022-11-24  发布在  其他
关注(0)|答案(2)|浏览(138)

我使用react和context:当我获取的项没有数据时,我发送null。null变成undefined(在res.send中)。在我的reducer中,当添加新项时,我使用spread运算符。这会导致错误,因为我试图spread undefined(当还没有项,后来添加了它的第一个undefined)。
什么是好的做法?在这种情况下,我应该怎么做才能将undefined更改为空数组?谢谢

const initialState = {
  isFetchingItems: null,
  items: [],
  fetchErrorMessage: null
}
const reducer = (state, action) => {
  switch (action.type) {
    case 'FETCH_ITEMS':
      return {
        ...state,
        isFetching: true
      }
    case 'FETCH_ITEMS_SUCCESS':
      return {
        ...state,
        items: action.payload.messages,
        isFetching: false
      }
    case 'FETCH_ITEMS_ERROR':
      return {
        ...state,
        fetchErrorMessage: action.payload,
        isFetching: false
      }
    case 'ADD_ITEMS_SUCCESS':
      return {
        ...state,
        items: [action.payload, ...state.items] // here the err comes from as its like [action.payload, ...undefined]
      }
    default:
      return state;
  }
};

我的动作:

const fetchItems = async() => {
  dispatch({ type: 'FETCH_ITEMS' })
  try {
    let items = await API.fetchItems();
    dispatch({ type: 'FETCH_Items_SUCCESS', payload: items })
  } catch (error) {
    dispatch({ type: 'FETCH_ITEMS_ERROR', payload: error.message })
  }
};

const fetchItems = async() => {
  // ...
  dispatch({ type: 'ADD_ITEMS_SUCCESS', payload: items })
  // ...
}
v440hwme

v440hwme1#

您可以使用nullish coalescing来实现简单明了的回退行为:

[action.payload, ...(state.items ?? [])]

如果state.itemsnullundefined,则将使用[]而不是state.items。否则,将使用state.items

kkbh8khc

kkbh8khc2#

问题

此问题不是维护状态不变,items状态最好 * 始终 * 为数组类型。此问题是由FETCH_ITEMS_SUCCESS操作接收null/undefined messages属性引起的,并且在ADD_ITEMS_SUCCESS操作尝试将项添加到state.items数组时暴露。

const initialState = {
  isFetchingItems: null,
  items: [],
  fetchErrorMessage: null
}

const reducer = (state, action) => {
  switch (action.type) {
    case 'FETCH_ITEMS':
      return {
        ...state,
        isFetching: true
      }
    case 'FETCH_ITEMS_SUCCESS':
      return {
        ...state,
        items: action.payload.messages, // <-- issue is caused here
        isFetching: false
      }
    case 'FETCH_ITEMS_ERROR':
      return {
        ...state,
        fetchErrorMessage: action.payload,
        isFetching: false
      }
    case 'ADD_ITEMS_SUCCESS':
      return {
        ...state,
        items: [action.payload, ...state.items] // <-- exposed here when undefined
      }
    default:
      return state;
  }
};

溶液

state.items不变式维持为数组。如果payload.messages属性为falsey,则提供空数组的有效后援值。

const initialState = {
  isFetchingItems: null,
  items: [],
  fetchErrorMessage: null
}

const reducer = (state, action) => {
  switch (action.type) {
    case 'FETCH_ITEMS':
      return {
        ...state,
        isFetching: true
      }
    case 'FETCH_ITEMS_SUCCESS':
      return {
        ...state,
        items: action.payload.messages ?? [], // <-- provide fallback
        isFetching: false
      }
    case 'FETCH_ITEMS_ERROR':
      return {
        ...state,
        fetchErrorMessage: action.payload,
        isFetching: false
      }
    case 'ADD_ITEMS_SUCCESS':
      return {
        ...state,
        items: [action.payload, ...state.items] // <-- now a safe operation
      }
    default:
      return state;
  }
};

这里的优化可能是***不***调度FETCH_ITEMS_SUCCESS操作,如果没有提取的项。
示例:

const fetchItems = async() => {
  dispatch({ type: 'FETCH_ITEMS' });
  try {
    const items = await API.fetchItems();

    if (items?.messages) {
      dispatch({ type: 'FETCH_Items_SUCCESS', payload: items });
    }
  } catch (error) {
    dispatch({ type: 'FETCH_ITEMS_ERROR', payload: error.message });
  }
};

相关问题