gpt4 book ai didi

javascript - 使用 TypeScript 在 React 组件之外调度 Redux Thunk 操作

转载 作者:搜寻专家 更新时间:2023-10-30 21:45:17 26 4
gpt4 key购买 nike

我正在将 React Native 应用程序转换为 TypeScript,但在商店外调度 thunk 操作时遇到了问题。以下是我的商店目前的设置方式:

store/index.ts

import { createStore, applyMiddleware, combineReducers, Reducer, Store } from 'redux';
import thunk, { ThunkMiddleware } from 'redux-thunk';

export interface State { ... }
export interface ActionTypes { ... } // All of the non-thunk actions

const reducer: Reducer<State> = combineReducers({ ... });

export default (): Store<State> => {
return applyMiddleware(
thunk as ThunkMiddleware<State, ActionTypes>
)(createStore)(reducer);
}

index.tsx

import { Provider } from 'react-redux';
import createStore from './store/index';
import { registerStore } from './store/registry';

const store = createStore();

registerStore(); // Registers the store in store/registry.ts

AppRegistry.registerComponent(appName, () => () => (
<Provider store={store}>
<App />
</Provider>
));

store/registry.ts

import { Store } from 'redux';
import { State } from './index';

let store: Store<State>;

export const registerStore = (newStore: Store<State>) => {
store = newStore;
};

export const getStore = () => store;

因此,当创建商店时,我将其存储在商店注册表中,这样我就可以调用 getStore()从任何地方。


这在组件(我不使用注册表的地方)中工作正常,例如在我的 App.tsx 中:

import { connect } from 'react-redux';
import { ThunkDispatch } from 'redux-thunk';
import { checkAuthStatus as checkAuthStatusAction } from './store/modules/auth/actions';
import { ActionTypes, State as AppState } from './store/index';

interface State = { ... }
interface StateProps { ... }
interface DispatchProps {
checkAuthStatus: () => Promise<boolean>;
}
type Props = StateProps & DispatchProps;

class App extends Component<Props, State> {
async componentDidMount() {
const promptSkipped: boolean = await checkAuthStatus(); // Thunk action, works fine!
}
...
}

const mapStateToProps = ...;
const mapDispatchToProps = (dispatch: ThunkDispatch<AppState, null, ActionTypes>): DispatchProps => ({
checkAuthStatus: () => dispatch(checkAuthStatusAction()),
});

export default connect<StateProps, DispatchProps, {}, AppState>(
mapStateToProps,
mapDispatchToProps,
)(App);

当我想使用注册表来发送 thunk 操作时,问题就来了:

lib/notacomponent.ts

import { getStore } from '../store/registry';
import { checkAuthStatus, setLoggedIn } from '../store/modules/auth/actions'

const someFunction = () => {
const store = getStore();

const { auth } = store.getState(); // Accessing state works fine!

store.dispatch(setLoggedIn(true)); // NON-thunk action, works fine!

store.dispatch(checkAuthStatus()); // Uh-oh, thunk action doesn't work.
}

这给了我错误:

Argument of type 'ThunkAction<Promise<boolean>, State, null, Action<any>>' is 
not assignable to parameter of type 'AnyAction'.

Property 'type' is missing in type 'ThunkAction<Promise<boolean>, State, null, Action<any>>'
but required in type 'AnyAction'. ts(2345)

据我所知,使用 thunk as ThunkMiddleware<State, ActionTypes>作为中间件,Redux Thunk 可以用一种可以调度 thunk 操作正常操作的方法替换商店调度方法。

我认为我需要以某种方式键入注册表,以便 TypeScript 可以看到调度方法不是仅允许正常操作的默认方法。但是,我不知道该怎么做。我找不到任何其他人做同样事情的例子。

感谢任何帮助。


编辑:建议重复How to dispatch an Action or a ThunkAction (in TypeScript, with redux-thunk)?不能解决我的问题。我可以在组件内部分发 thunk Action 。使用上面定义的商店注册表,我只有组件外部的问题。


编辑 2:看来我可以在分派(dispatch) thunk 操作时使用以下类型断言来消除错误:

(store.dispatch as ThunkDispatch<State, void, ActionTypes>)(checkAuthStatus())

虽然这是非常不切实际的。我还没有找到一种方法来让 TypeScript 知道 dispatch方法应该始终能够分派(dispatch) thunk 操作。

最佳答案

您的代码几乎是正确的。您错误地设置了默认导出的返回类型。

export default (): Store<State> => {
return applyMiddleware(
thunk as ThunkMiddleware<State, ActionTypes>
)(createStore)(reducer);
}

在使用中间件的情况下,上面的函数不应返回 Store<State> ,但是 Store<S & StateExt, A> & Ext其中 Ext会重载dispatch这将能够 dispatch functions (就像 redux-thunk 一样)。

为了简化,只需删除确切的返回类型并让 TypeScript 自行推断类型

export default () => {
return applyMiddleware(
thunk as ThunkMiddleware<State, ActionTypes>
)(createStore)(reducer);
}

这就解决了你的问题。

或者,您可以使用更经典的方法来创建商店。

export default () => {
return createStore(reducer, applyMiddleware(thunk as ThunkMiddleware<State, ActionTypes>));
}

这里有基本的东西:

  1. 使用 createStore根据 Redux official doc 的推荐. createStore用中间件作为第二个参数调用本身 call it .但是 redux 和 redux-thunk 的 TypeScript 声明文件是为这种使用预先配置的 createStore .所以返回的商店将有 modified versiondispatch . (记下 Ext and StateExtStoreEnhancer<Ext, StateExt> 类型参数。它们将与结果存储相交,并添加将接受函数作为参数的 dispatch 的重载版本。

  2. 默认导出函数的返回类型也将从 createStore 推断出来的返回类型。它不会是 Store<State> .

关于javascript - 使用 TypeScript 在 React 组件之外调度 Redux Thunk 操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56498212/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com