[英]next-redux-wrapper in getServerSideProps in nextjs
[英]how to use typescript, next-redux-wrapper, getServerSideProps?
你好,我想要 javascript -> 打字稿! 但是,太難了..
幫助!!!
// store.js
import { applyMiddleware, createStore, compose, Store } from "redux";
import createSagaMiddleware, { Task } from "redux-saga";
import { createWrapper } from "next-redux-wrapper";
import { composeWithDevTools } from "redux-devtools-extension";
import reducer from "./reducers";
import rootSaga from "./sagas";
const configureStore = () => {
const sagaMiddleware = createSagaMiddleware();
const middlewares = [sagaMiddleware];
const enhancer =
process.env.NODE_ENV === "production"
? compose(applyMiddleware(...middlewares))
: composeWithDevTools(applyMiddleware(...middlewares));
const store = createStore(reducer, enhancer);
store.sagaTask = sagaMiddleware.run(rootSaga);
return store;
};
const wrapper = createWrapper(configureStore, {
debug: process.env.NODE_ENV === "development",
});
export default wrapper;
// reducers/index.ts
import { HYDRATE } from "next-redux-wrapper";
import { AnyAction, combineReducers } from "redux";
import url, { IUrlReducerState } from "./reducer_url";
import user, { IUserReducerState } from "./reducer_user";
export type State = {
url: IUrlReducerState;
user: IUserReducerState;
};
const rootReducer = (state: State, action: AnyAction) => {
switch (action.type) {
case HYDRATE:
return action.payload;
default: {
const combineReducer = combineReducers({
url,
user,
});
return combineReducer(state, action);
}
}
};
export type RootState = ReturnType<typeof rootReducer>;
export default rootReducer;
reducers/index.ts <- 你是這樣做的嗎? 我已經稍微改變了它。
// pages/index.js
import { END } from "redux-saga";
import wrapper from "../store";
export const getServerSideProps = wrapper.getServerSideProps(
async (context) => {
context.store.dispatch({
type: LOAD_USER_REQUEST,
});
context.store.dispatch(END);
await context.store.sagaTask.toPromise();
}
);
看了官方文檔,沒看懂。 [https://github.com/kirill-konshin/next-redux-wrapper#getserversideprops]
這些代碼在 JavaScript 中沒有問題。 但是打字稿有問題。
我英語說的不好。 對不起..
所以想要簡單的代碼,簡單的描述。
謝謝。
以下是我看到的問題:
createStore(reducer, enhancer)
(state: State | undefined, action: AnyAction) => State
收到錯誤,因為您的reducer
不適合類型(state: State | undefined, action: AnyAction) => State
。 您必須使您的減速器適合這種類型。 現在的問題是您的減速器不允許state
為undefined
。改變
const rootReducer = (state: State, action: AnyAction) => {
到
const rootReducer = (state: State | undefined, action: AnyAction): State => {
store.sagaTask = sagaMiddleware.run(rootSaga);
行上收到錯誤store.sagaTask = sagaMiddleware.run(rootSaga);
因為 redux 創建的store
對象沒有名為sagaTask
的屬性。 有一個關於另一個討論在這里。這是一個基於 next-redux-wrapper 文檔的解決方案:
為您的商店定義一個包含任務的新界面
export interface SagaStore extends Store<State, AnyAction> {
sagaTask: Task;
}
代替
store.sagaTask = sagaMiddleware.run(rootSaga);
和
(store as SagaStore).sagaTask = sagaMiddleware.run(rootSaga);
代替
await context.store.sagaTask.toPromise();
和
await (context.store as SagaStore).sagaTask.toPromise();
我在嘗試以適當的方式將 Redux 與 Next 同步時也遇到了一些糟糕的情況,他們使用 next-redux-wrapper 創建了一個項目模板,該模板目前正在工作並遵循 next-redux-wrapper 的指導方針. 你可以看看:
https://github.com/felipemeriga/next-typescript-redux-template
基本上我創建了這樣的包裝器:
const thunkMiddleware = thunk.withExtraArgument({}) as ThunkMiddleware<IStoreState, AnyAction>;
// create a makeStore function
// This makeStore is needed for the wrapper, for every new page that is called, a new store with the current values will be created
const makeStore: MakeStore<IStoreState> = (context: Context) => createStore(reducers, composeWithDevTools(applyMiddleware(thunkMiddleware)));
export type ExtraArgument = {};
export type ThunkCreator<R = Promise<any>> = ActionCreator<ThunkAction<R, IStoreState, ExtraArgument, AnyAction>>;
// export an assembled wrapper
// this wrapper will be used to every page's component, for injecting the store and actions into it.
const wrapper = createWrapper<IStoreState>(makeStore, {debug: false});
export default wrapper;
然后覆蓋_app.tsx:
// For default you don't need to edit _app.tsx, but if you want to wrapper the pages with redux wrapper, you need
// to override _app.tsx with this code bellow
class MyApp extends App {
// @ts-ignore
static async getInitialProps({Component, ctx}) {
return {
pageProps: {
// Call page-level getInitialProps
...(Component.getInitialProps ? await Component.getInitialProps(ctx) : {}),
}
};
}
render() {
const {Component, pageProps} = this.props;
return (
<Component {...pageProps} />
);
}
}
export default wrapper.withRedux(MyApp);
最后注入 index.tsx 組件:
interface IProps {
tick: ITickState
updateAnnouncement: any
}
interface IState {}
interface IDispatchProps {
onUpdateTick: (message: string) => ITickState,
thunkAsyncFunction: () => Promise<any>;
}
type Props = IProps & IState & IDispatchProps
class App extends React.Component<Props> {
constructor(props: Props) {
super(props);
}
async componentWillUnmount(): Promise<void> {
await this.props.thunkAsyncFunction();
}
render() {
return (
<Layout title="Home | Next.js + TypeScript Example">
<h1>Hello Next.js 👋</h1>
<p>
<Link href="/about">
<a>About</a>
</Link>
</p>
<div>
The current tick state: {this.props.tick.message}
</div>
</Layout>
);
}
}
const mapStateToProps = (state: IStoreState): {tick: ITickState} => ({
tick: getTickState(state)
});
const mapDispatchToProps = (dispatch: any): IDispatchProps => {
return {
onUpdateTick: (message: string) =>
dispatch(updateTick(message)),
thunkAsyncFunction: () => dispatch(thunkAsyncFunction())
}
};
export default connect(mapStateToProps, mapDispatchToProps)(App);
// As the wrapper is injected in _app.tsx, for every component(page) that will interact with Redux and Thunk
// you need to place this piece of code bellow, that will get the static props from the wrapper, and inject on your
// component
export const getStaticProps = wrapper.getStaticProps(
({}) => {
}
);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.