Javascript 为什么这个createAsyncThunk行为异常?

Javascript 为什么这个createAsyncThunk行为异常?,javascript,reactjs,redux,redux-toolkit,Javascript,Reactjs,Redux,Redux Toolkit,我对redux工具包API中的createAsyncThunk有一些问题 export const getPayments = createAsyncThunk('getPayments/all', async ({ rejectWithValue }) => { try { const response = await fetch(`/payments`, { method: 'GET', headers: { 'C

我对redux工具包API中的
createAsyncThunk
有一些问题

export const getPayments = createAsyncThunk('getPayments/all', async ({ rejectWithValue }) => {
    try {
        const response = await fetch(`/payments`, {
            method: 'GET',
            headers: { 'Content-Type': 'application/json' },
        })
        console.log('res:', response)
        return response
    } catch (e) {
        console.log('ERROR:', e)
        rejectWithValue(e)
    }
})
每当我添加
rejectWithValue
作为参数时,它总是在redux开发工具中显示为rejected。当我移除它时,它总是满足的。这是怎么回事?我只想调用下面的这个函数,如果提取时出错?为什么它总是拒绝它


编辑:我发现此
无法对“undefined”的属性“rejectWithValue”进行解构,因为它是未定义的。
在现在的响应中,这说明了为什么它总是被拒绝,为什么会发生这种情况,以及我如何修复它?

下面是一个示例,如前所述,的
rejectWithValue
第二个参数的属性,有效负载创建者需要返回
rejectWithValue
调用的结果,以下是一个示例:

// toggle reject
const reject = ((shouldReject) => () =>
  (shouldReject = !shouldReject))(true);
// test thunk action creator
const testAsyncThunk = createAsyncThunk(
  'some/test',
  //  arg is the argument passed to the action creator, can be ignored if not used
  async (arg, { rejectWithValue }) => {
    console.log('argument passed to action creator:', arg);
    if (reject()) {
      //return result of rejectWithValue call
      return rejectWithValue('rejected');
    }
    return Promise.resolve('resolved');
  }
);
当您分派使用
createAsyncThunk
创建的thunk时,除非您使用
unwrapResult
,否则结果承诺

下面是一个演示该行为的小应用程序:

import React from 'react';
import ReactDOM from 'react-dom';
import {
  createAsyncThunk,
  unwrapResult,
} from '@reduxjs/toolkit';

import { Provider, useDispatch } from 'react-redux';
import {
  createStore,
  applyMiddleware,
  compose,
} from 'redux';

// toggle reject
const reject = ((shouldReject) => () =>
  (shouldReject = !shouldReject))(true);
// test thunk action creator
const testAsyncThunk = createAsyncThunk(
  'some/test',
  //  arg is the argument passed to the action creator, can be ignored if not used
  async (arg, { rejectWithValue }) => {
    console.log('argument passed to action creator:', arg);
    if (reject()) {
      //return result of rejectWithValue call
      return rejectWithValue('rejected value');
    }
    return Promise.resolve('resolved value');
  }
);

const reducer = (state, { type, payload }) => {
  return state;
};
//creating store with redux devtools and thunk middleware
const composeEnhancers =
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
  reducer,
  {},
  composeEnhancers(
    applyMiddleware(
      ({ dispatch, getState }) => (next) => (action) =>
        //minimal implementation of thunk middleware
        typeof action === 'function'
          ? action(dispatch, getState)
          : next(action)
    )
  )
);
const App = () => {
  const dispatch = useDispatch();
  return (
    <button
      onClick={() =>
        dispatch(testAsyncThunk('argument passed'))
          .then(
            (resolved) => {
              console.log('action resolved with', resolved);
              return resolved;
            },
            (rejected) =>
              // this never executes because promise returned
              //   by dispatch(tunkaction) will not reject
              console.log('action rejected with:', rejected)
          )
          .then(
            //after unwrap result you have a promise that will
            //  reject
            unwrapResult
          )
          .catch((err) =>
            console.log('rejected with...', err)
          )
      }
    >
      dispatch action
    </button>
  );
};

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
从“React”导入React;
从“react dom”导入react dom;
进口{
创建异步thunk,
展开结果,
}来自“@reduxjs/toolkit”;
从“react redux”导入{Provider,useDispatch};
进口{
createStore,
applyMiddleware,
组成
}来自“redux”;
//切换拒绝
常量拒绝=((shouldReject)=>()=>
(shouldReject=!shouldReject))(true);
//测试thunk动作创建者
const testAsyncThunk=createAsyncThunk(
“一些/测试”,
//arg是传递给动作创建者的参数,如果不使用,可以忽略
异步(arg,{rejectWithValue})=>{
log('传递给操作创建者的参数:',arg);
if(拒绝()){
//返回rejectWithValue调用的结果
返回rejectWithValue(“拒绝值”);
}
返回承诺。解析(“解析值”);
}
);
const reducer=(状态,{type,payload})=>{
返回状态;
};
//使用redux开发工具和thunk中间件创建存储
康斯特康塞恩汉斯酒店=
窗口。uuu REDUX_vtools_uextension_uuucompose_uu124; COMPOSE;
const store=createStore(
减速器,
{},
复合致癌物(
applyMiddleware(
({dispatch,getState})=>(下一步)=>(操作)=>
//thunk中间件的最小实现
动作类型===‘功能’
?行动(调度、获取状态)
:下一步(行动)
)
)
);
常量应用=()=>{
const dispatch=usedpatch();
返回(
分派(testAsyncThunk('参数已传递'))
.那么(
(已解决)=>{
console.log('action resolved with',resolved);
返回已解决;
},
(被拒绝)=>
//这永远不会执行,因为承诺已经兑现
//通过派遣(tunkaction)不会拒绝
console.log('操作已被拒绝,已被拒绝:')
)
.那么(
//在打开结果后,你有一个承诺
//拒绝
展开结果
)
.catch((错误)=>
console.log('被…拒绝',错误)
)
}
>
派遣行动
);
};
ReactDOM.render(
,
document.getElementById('root'))
);

我认为您应该为异步函数添加第一个属性,例如:async(data,{rejectWithValue})..@AlekseyDubinskiy但我不需要此实例中的任何数据?即使我输入了数据,它仍然会触发“Completed”,即使它跳入catch块??您还需要返回拒绝
return rejectWithValue(e)
即使不需要数据,
thunkApi
也将作为第二个参数传入该函数。就像JavaScript中的所有地方一样:如果您关心第二个参数而不是第一个参数,那么您仍然需要给第一个参数起一个名字,否则您将永远无法得到第二个参数。不一定是
数据
<代码>\u可能是一个很好的选择,表明您不关心它。好的,谢谢。我修好了,但我有个问题。我在
createAsyncThunk
中有一个fetch,我在里面放了一个try-catch,它从未“拒绝”过它。甚至当它进入捕捉区时。但是当我删除try/catch并从fetch返回结果时。成功了吗?(也就是说,根据服务器的响应,它要么转到
.completed
要么
.rejected
。为什么try/catch不起作用?@RedBaron你确定你在catch块中返回
return rejectWithValue(someError);
吗?不,我想这可能起作用。稍后再试,让你知道