无法在 createAsyncThunk 中将 getState 类型设置为 RootState
Cannot set getState type to RootState in createAsyncThunk
我无法将 getState()
的 return 类型设置为 RootState
。我正在使用打字稿和 VSCode。我必须将类型设置为 any
,这会停止对该对象的 IntelliSense。下面是有问题的代码:
export const unsubscribeMeta = createAsyncThunk(
'meta/unsubscribe',
async (_, { getState }) => {
const { meta } = getState() as any;
const res = await client.post<apiUnsubscribeResponse>(
`/meta/unsubscribe/${meta.subscriptionId}`
);
return res.data.data;
}
);
如果我尝试使用 RootState
而不是 any
,模块中的许多错误会被 VSCode 标记。我相信这是由于对商店和这个切片的循环依赖。我在选择器模块中的许多地方使用 RootState
,没有问题。有解决办法吗?
你真的不需要知道整个州的形状。您只需要知道您尝试访问的值是否存在。
如果您可以访问整个 state.meta
类型:
const { meta } = getState() as { meta: MetaState };
如果没有:
const { meta } = getState() as { meta: { subscriptionId: string } };
我推荐这种方法来避免循环依赖,因为根状态将始终依赖于切片,所以切片不应该依赖于根。
只需从您的 ThunkApiConfig
类型中省略 state: RootState
,然后您就可以在您的 payloadCreator 中使用 const state = getState() as RootState;
而无需循环依赖。
createAsyncThunk
可以具有在泛型上定义的类型:
export const unsubscribeMeta = createAsyncThunk<apiUnsubscribeResponse, void, {state: RootState }>(
'meta/unsubscribe',
async (_, { getState }) => {
const { meta } = getState();
const res = await client.post<apiUnsubscribeResponse>(
`/meta/unsubscribe/${meta.subscriptionId}`
);
return res.data.data;
}
);
定义 state
将自动使 getState 了解应用程序状态。
您可以使用 Typescript 的 module augmentation 功能将默认状态分配给 AsyncThunkConfig.state
,这将是我们稍后调用它时 getState()
的返回类型。
declare module "@reduxjs/toolkit" {
type AsyncThunkConfig = {
state?: unknown;
dispatch?: Dispatch;
extra?: unknown;
rejectValue?: unknown;
serializedErrorType?: unknown;
};
function createAsyncThunk<
Returned,
ThunkArg = void,
ThunkApiConfig extends AsyncThunkConfig = {
state: YourRootState; // this line makes a difference
}
>(
typePrefix: string,
payloadCreator: AsyncThunkPayloadCreator<
Returned,
ThunkArg,
ThunkApiConfig
>,
options?: any
): AsyncThunk<Returned, ThunkArg, ThunkApiConfig>;
}
其中 YourRootState
是您的商店状态的类型。
type YourRootState = {
myNumber: number;
myString: string;
};
现在您可以像往常一样使用 createAsyncThunk
和 getState()
returns 正确的类型。
const doSomethingAsync = createAsyncThunk(
"mySlice/action",
async (_, { getState, dispatch }) => {
const rootState = getState(); // has type YourRootState
console.log(rootState.myNumber);
console.log(rootState.myString);
}
);
function Child() {
const dispatch = useDispatch();
return <button onClick={() => dispatch(doSomethingAsync())}>Click</button>;
}
现场演示
我将继续 NearHuscarl 的回答,因为我无法建议对其进行修改。
NearHuscarl 的回答很好,但是问题是他将 options
类型设置为 any
,因此它解决了一个问题,如果您在其中使用 options
createAsyncThunk
您必须手动设置其所有类型,否则 typescript
将引发 Binding element implicitly has an 'any' type.
错误。
所以只需像下面这样设置 options
类型就可以解决这个问题。
declare module "@reduxjs/toolkit" {
type AsyncThunkConfig = {
state?: unknown;
dispatch?: Dispatch;
extra?: unknown;
rejectValue?: unknown;
serializedErrorType?: unknown;
};
function createAsyncThunk<
Returned,
ThunkArg = void,
ThunkApiConfig extends AsyncThunkConfig = { state: RootState } // here is the magic line
>(
typePrefix: string,
payloadCreator: AsyncThunkPayloadCreator<
Returned,
ThunkArg,
ThunkApiConfig
>,
options?: AsyncThunkOptions<ThunkArg, ThunkApiConfig>,
): AsyncThunk<Returned, ThunkArg, ThunkApiConfig>;
}
我无法将 getState()
的 return 类型设置为 RootState
。我正在使用打字稿和 VSCode。我必须将类型设置为 any
,这会停止对该对象的 IntelliSense。下面是有问题的代码:
export const unsubscribeMeta = createAsyncThunk(
'meta/unsubscribe',
async (_, { getState }) => {
const { meta } = getState() as any;
const res = await client.post<apiUnsubscribeResponse>(
`/meta/unsubscribe/${meta.subscriptionId}`
);
return res.data.data;
}
);
如果我尝试使用 RootState
而不是 any
,模块中的许多错误会被 VSCode 标记。我相信这是由于对商店和这个切片的循环依赖。我在选择器模块中的许多地方使用 RootState
,没有问题。有解决办法吗?
你真的不需要知道整个州的形状。您只需要知道您尝试访问的值是否存在。
如果您可以访问整个 state.meta
类型:
const { meta } = getState() as { meta: MetaState };
如果没有:
const { meta } = getState() as { meta: { subscriptionId: string } };
我推荐这种方法来避免循环依赖,因为根状态将始终依赖于切片,所以切片不应该依赖于根。
只需从您的 ThunkApiConfig
类型中省略 state: RootState
,然后您就可以在您的 payloadCreator 中使用 const state = getState() as RootState;
而无需循环依赖。
createAsyncThunk
可以具有在泛型上定义的类型:
export const unsubscribeMeta = createAsyncThunk<apiUnsubscribeResponse, void, {state: RootState }>(
'meta/unsubscribe',
async (_, { getState }) => {
const { meta } = getState();
const res = await client.post<apiUnsubscribeResponse>(
`/meta/unsubscribe/${meta.subscriptionId}`
);
return res.data.data;
}
);
定义 state
将自动使 getState 了解应用程序状态。
您可以使用 Typescript 的 module augmentation 功能将默认状态分配给 AsyncThunkConfig.state
,这将是我们稍后调用它时 getState()
的返回类型。
declare module "@reduxjs/toolkit" {
type AsyncThunkConfig = {
state?: unknown;
dispatch?: Dispatch;
extra?: unknown;
rejectValue?: unknown;
serializedErrorType?: unknown;
};
function createAsyncThunk<
Returned,
ThunkArg = void,
ThunkApiConfig extends AsyncThunkConfig = {
state: YourRootState; // this line makes a difference
}
>(
typePrefix: string,
payloadCreator: AsyncThunkPayloadCreator<
Returned,
ThunkArg,
ThunkApiConfig
>,
options?: any
): AsyncThunk<Returned, ThunkArg, ThunkApiConfig>;
}
其中 YourRootState
是您的商店状态的类型。
type YourRootState = {
myNumber: number;
myString: string;
};
现在您可以像往常一样使用 createAsyncThunk
和 getState()
returns 正确的类型。
const doSomethingAsync = createAsyncThunk(
"mySlice/action",
async (_, { getState, dispatch }) => {
const rootState = getState(); // has type YourRootState
console.log(rootState.myNumber);
console.log(rootState.myString);
}
);
function Child() {
const dispatch = useDispatch();
return <button onClick={() => dispatch(doSomethingAsync())}>Click</button>;
}
现场演示
我将继续 NearHuscarl 的回答,因为我无法建议对其进行修改。
NearHuscarl 的回答很好,但是问题是他将 options
类型设置为 any
,因此它解决了一个问题,如果您在其中使用 options
createAsyncThunk
您必须手动设置其所有类型,否则 typescript
将引发 Binding element implicitly has an 'any' type.
错误。
所以只需像下面这样设置 options
类型就可以解决这个问题。
declare module "@reduxjs/toolkit" {
type AsyncThunkConfig = {
state?: unknown;
dispatch?: Dispatch;
extra?: unknown;
rejectValue?: unknown;
serializedErrorType?: unknown;
};
function createAsyncThunk<
Returned,
ThunkArg = void,
ThunkApiConfig extends AsyncThunkConfig = { state: RootState } // here is the magic line
>(
typePrefix: string,
payloadCreator: AsyncThunkPayloadCreator<
Returned,
ThunkArg,
ThunkApiConfig
>,
options?: AsyncThunkOptions<ThunkArg, ThunkApiConfig>,
): AsyncThunk<Returned, ThunkArg, ThunkApiConfig>;
}