【问题标题】:TypeScript with Redux. Redux Saga How to wait for the LOAD_SUCCESS to return and save your data for later use带有 Redux 的 TypeScript。 Redux Saga 如何等待 LOAD_SUCCESS 返回并保存数据以备后用
【发布时间】:2020-10-07 14:38:27
【问题描述】:

我不熟悉使用 redux 和 redux-saga。

当操作发送到 API 时,我无法检索对象的信息。 当我在“promocoesSagas”中第一次使用日志时返回null,它只是在LOAD_REQUEST成功后才与对象一起返回,这很明显。 我应该采取什么方法让我的应用程序等待接收这些数据? 因为如果我调用一个

const promocoesItems = promocoesSagas.data.item;

应用程序因“LOAD_REQUEST”尚未加载数据而中断,第一次返回null。 First time call Trying access the value

我的 useEffect 钩子:

const List = () => {
...

const promocoesSagas = useSelector((state: AppState) => state.promocoes);   
console.log(promocoesSagas);
const promocoesItem = promocoesSagas.data.items;
console.log(promocoesItem);

const dispatch = useDispatch<Dispatch<PromocoesActions>>();

 useEffect(() => {
   (async () => {
     setIsloading(true);
     try {
       dispatch({ type: PromocoesActionTypes.LOAD_REQUEST, payload: query });
     } catch (error) {
       const errorResult: ErrorResult = error;
       if (
         errorResult.result != null &&
         errorResult.result.statusCode === 403
       ) {
         push('/error-403');
         return;
       }
       message.error(errorResult.message);
     }
     setIsloading(false);
  })();
}, [query, refetch]);

   return (...)}

actions.ts

const loadPromocoesAsync = createAsyncAction(
 PromocoesActionTypes.LOAD_REQUEST,
 PromocoesActionTypes.LOAD_SUCCESS,
 PromocoesActionTypes.LOAD_FAILURE,
)<PromocoesQuery, FetchResult<PromocoesModel>, undefined>();

 export { loadPromocoesAsync };

减速器

const INITIAL_STATE: PromocoesState = {
  data: null,
  error: false,
  loading: false,
};

const reducer: Reducer<PromocoesState> = (
  state = INITIAL_STATE,
  action: PromocoesActions,
) => {
  switch (action.type) {
    case PromocoesActionTypes.LOAD_REQUEST:
      return { ...state, loading: true };
    case PromocoesActionTypes.LOAD_SUCCESS:
      return { ...state, loading: false, error: false, data: action.payload };
    case PromocoesActionTypes.LOAD_FAILURE:
      return { ...state, loading: false, error: true };
    default:
      return state;
  }
};

sagas.ts

function* load(action: ReturnType<typeof loadPromocoesAsync.request>) {
  try {
    const query = action.payload;
    const response: FetchResult<PromocoesModel> = yield call(
      api.getPromocoes,
      query,
    );
    yield put(loadPromocoesAsync.success(response));
  } catch (err) {
    yield put(loadPromocoesAsync.failure());
  }
}

export { load };

types.ts

type PromocoesActions = ActionType<typeof promocoesActions>;

enum PromocoesActionTypes {
  LOAD_REQUEST = 'LOAD_REQUEST',
  LOAD_SUCCESS = 'LOAD_SUCCESS',
  LOAD_FAILURE = 'LOAD_FAILURE',
}

interface PromocoesState {
  readonly data: FetchResult<PromocoesModel> | null;
  readonly loading: boolean;
  readonly error: boolean;
}

export { PromocoesActions, PromocoesActionTypes, PromocoesState };

root-reducer

const rootReducer = combineReducers({
  promocoes,
});

export type AppState = ReturnType<typeof rootReducer>;

export default rootReducer;

根传奇

export default function* rootSaga() {
  return yield all([takeLatest(loadPromocoesAsync.request, load)]);
}

【问题讨论】:

  • 你想在哪里使用 promocoesItem...看来你只是想在console.log的函数组件体中访问它?
  • 抱歉,如果我无法添加任何必要的信息。在您发表评论后,我看到我的另一个组件得到了错误的返回,并且在我仍在加载的信息传递给另一个组件之前刚刚放置了一个 console.log ()。
  • 那么你还在努力解决这个问题,还是已经解决了?
  • 已解决,我只是在添加缺少的内容。

标签: reactjs typescript react-redux react-hooks redux-saga


【解决方案1】:

在 Seth Lutske 做出回应后,我意识到我的其他组件获取了错误的数据类型。在 LOAD_REQUEST 完成工作之前,我刚刚放了一个“console.log ()”。

以前的情况:

    const List = () => {
    ...
    
    useEffect(()=>{...},[query, refetch]);

           return(
              <PromocoesTable
                currentPage={query.pagination.page}
                isLoading={isLoading}
                pageItems={promocoes != null ? promocoes.items : []}
                onChange={(evt) => setQuery({ ...query, ...evt })}
                totalItems={promocoes != null ? promocoes.totalItems : 0}
                initialPageSize={query.pagination.pageSize}
                onAction={onTableAction}
              />
        )
}

变成了:

        const List = () => {
        ...
        
        useEffect(()=>{...},[query, refetch]);

    return(
        <PromocoesTable
            currentPage={query.pagination.page}
            isLoading={isLoading}
            pageItems={promocoesSagas.data != null ? promocoesSagas.data.items : []}
            onChange={(evt) => setQuery({ ...query, ...evt })}
            totalItems={
              promocoesSagas.data != null ? promocoesSagas.data.totalItems : 0
            }
            initialPageSize={query.pagination.pageSize}
            onAction={onTableAction}
          />
    )
}

对不起,如果这是一个非常简单的问题,这是我的错误。 下次我会试试橡皮鸭。

【讨论】:

    【解决方案2】:

    你几乎准备好了,你只需要在 react 应用程序中处理你的 redux 变量,我建议在 List 组件中做这样的事情,记住你的 promocoes reducer 已经有了加载或错误变量:

    // Here you grab the values from the store, you don't need any local state.
    const {data, loading, error, } = useSelector((state: AppState) => state.promocoes);
    
    const dispatch = useDispatch<Dispatch<PromocoesActions>>();
    
    // Your useEffect can be simplified, because your api call is already handled by the saga
    
    useEffect(() => {
       dispatch({ type: PromocoesActionTypes.LOAD_REQUEST, payload: query });
    }, [query, refetch]); 
    
    if (loading) return <p>Loading...</p>
    
    if (error) return message.error(errorResult.message)
    
    // Assuming data is an array
    return data && data.length > 0 && (
      // Your component
    )
    

    【讨论】:

    • 感谢您的提示。
    猜你喜欢
    • 2021-07-26
    • 2018-06-18
    • 2019-05-13
    • 1970-01-01
    • 2023-03-24
    • 2019-03-18
    • 2019-04-25
    • 1970-01-01
    • 2017-01-28
    相关资源
    最近更新 更多