redux 数据并不总是来自API

iswrvxsc  于 2023-03-30  发布在  其他
关注(0)|答案(3)|浏览(89)

我需要你的帮助。我在我的应用程序中使用react和redux沿着typescript。使用下面的代码,我得到了我的产品和它们的类别。事实是,我得到了我的产品,它们看起来很棒,但类别工作得不是很好:有时我必须重新加载页面几次才能显示它们,有时我不这样做。告诉我如何修复它?非常感谢
Api服务

export const getAllCategories = () => {
    return async (dispatch: Dispatch<ProductActionModel>, getState: () => RootState) => {
        try {
            dispatch({ type: Action_types.GET_ALL_CATEGORIES });
            const response = await fetch(`${environment.baseApiUrl}/products/categories`).then(res => res.json());
            const state = getState();
            dispatch({ type: Action_types.GET_ALL_CATEGORIES_SUCCESS, payload: [...state.products.categories, ...response] });
        } catch (error) {
            dispatch({ type: Action_types.GET_ALL_CATEGORIES_ERROR, payload: 'Something went wrong'})
        }
    }
}

export const getAllProducts = () => {
    return async (dispatch: Dispatch<ProductActionModel>) => {
        try {
            dispatch({ type: Action_types.GET_ALL_PRODUCTS });
            const response = await fetch(`${environment.baseApiUrl}/products`).then(response => response.json())
            dispatch({ type: Action_types.GET_PRODUCTS_SUCCESS, payload: response.products })
        } catch (e) {
            dispatch({ type: Action_types.GET_PRODUCTS_ERROR, payload: 'Something went wrong' });
        }
    }
}

产品减速器

const initialState: ProductsStateModel = {
    products: [],
    categories: [],
    loading: false,
    error: null
}

export const ProductReducer = (state = initialState, action: ProductActionModel): ProductsStateModel => {
    switch (action.type) {

        case Action_types.GET_ALL_PRODUCTS:
            return { loading: true, error: null, products: [], categories: [] }
        case Action_types.GET_PRODUCTS_ERROR:
            return { loading: false, error: action.payload, products: [], categories: [] }
        case Action_types.GET_PRODUCTS_SUCCESS:
            return { loading: false, error: null, products: action.payload, categories: [] }
        case Action_types.GET_ALL_CATEGORIES:
            return state;
        case Action_types.GET_ALL_CATEGORIES_ERROR:
            return state;
        case Action_types.GET_ALL_CATEGORIES_SUCCESS:
            return { ...state, categories: [...state.categories, ...action.payload] }
        default:
            return state;
    }
}

产品列表

const { products, error, loading, categories } = useTypesSelector(state => state.products);
    const dispatch: ThunkDispatch<RootState, void, ProductActionModel> = useDispatch();

    useEffect(() => {
        dispatch(getAllProducts());
        dispatch(getAllCategories())
    },[dispatch])

    console.log(categories); // sometimes fine, sometimes [], [], [categories], []
sxissh06

sxissh061#

看起来你想按顺序执行reducer。你能像下面这样做链接吗?

const { products, error, loading, categories } = useTypesSelector(state => state.products);
const dispatch: ThunkDispatch<RootState, void, ProductActionModel> = useDispatch();

useEffect(() => {
    dispatch(getAllProducts()).then(()=>dispatch(getAllCategories()));
},[dispatch])

console.log(categories); // sometimes fine, sometimes [], [], [categories], []

或者,创建一个包含getAllProducts()和getAllCategories()的reducer。

export const getAllCategories = () => {
return async (dispatch: Dispatch<ProductActionModel>, getState: () => RootState) => {
    try {
        dispatch({ type: Action_types.GET_ALL_CATEGORIES });
        const response = await fetch(`${environment.baseApiUrl}/products/categories`).then(res => res.json());
        const state = getState();
        dispatch({ type: Action_types.GET_ALL_CATEGORIES_SUCCESS, payload: [...state.products.categories, ...response] });
    } catch (error) {
        dispatch({ type: Action_types.GET_ALL_CATEGORIES_ERROR, payload: 'Something went wrong'})
    }
}}

export const getAllProducts = () => {
return async (dispatch: Dispatch<ProductActionModel>) => {
    try {
        dispatch({ type: Action_types.GET_ALL_PRODUCTS });
        const response = await fetch(`${environment.baseApiUrl}/products`).then(response => response.json())
        dispatch({ type: Action_types.GET_PRODUCTS_SUCCESS, payload: response.products })
    } catch (e) {
        dispatch({ type: Action_types.GET_PRODUCTS_ERROR, payload: 'Something went wrong' });
    }
}}

export const initialLoader= () => {
return async (dispatch: Dispatch<ProductActionModel>, getState: () => RootState) => { // Unify above functions}}
dddzy1tm

dddzy1tm2#

从代码中我可以理解
console.log(categories); // sometimes fine, sometimes [], [], [categories], []
组件将重新呈现每次状态更新(这里我的意思是redux商店)。
当组件挂载时,最初你的类别是空的,比如[],(console.log中的第一个[]),然后当你加载产品时组件重新渲染(console.log中的第二个[]),
最后,在实际加载类别时更新状态(即在console.log中获取[categories]时)
现在你应该在你的商店中有一个指示器,指示你的API正在加载类别,并且你不应该处理类别,直到它从api加载。
我可以看到,有装载标志的国家,但它只用于产品装载指示。希望这将有助于您。

cgh8pdjw

cgh8pdjw3#

看起来你必须处理很多状态。我建议使用React Query。useQueries钩子可以用来获取可变数量的请求。

const results = useQueries([
  { queryKey: ['products'], queryFn: yourProductsFetchFunction},
  { queryKey: ['categories'], queryFn: yourCategoriesFetchFunction },
])

正如文档所说,TanstackQuery为您提供了非常有用的状态,您可以知道您的数据是否成功或未解决,这将有助于您处理问题。要获取第一个查询的加载状态,您可以使用results[0].isLoading。一些states是:
isError或status === 'error' -查询遇到错误
isSuccess或status === 'success' -查询成功,数据可用
isIdle或status === 'idle' -查询当前被禁用(稍后您将了解更多有关此内容的信息)

相关问题