如何使用打字稿,next-redux包装器,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中没有问题。 但是打字稿有问题。

我英语不好。抱歉。

所以想要简单的代码,简单的说明。

谢谢。

解决方法

这是我看到的问题:

  1. 您将在class GUI(tk.Tk): """GUI created from Tkinter""" def __init__(self,start_values: Dict[str,Any],mode: str = 'auto',verbose: Optional[int] = 3 ) -> None: super().__init__() self.mode = mode self.start_values = start_values self.current_state = self.mode # GUI window self.title("Graphic User Interface") self.verbose = verbose # Maximizes window when exiting fullscreen mode # self.state('zoomed') # <-- not supported in Linux self.attributes("-fullscreen",True) self.configure(background=background_color) self.bind("<Escape>",self.end_fullscreen) self.columnconfigure(0,weight=1) self.rowconfigure(2,weight=1) # Title title = tk.Label( self,text="Auto/manual mode",bg=background_color,font=("Bodoni bold",45)) title.grid() style = ttk.Style() style.theme_create( "MyStyle",parent="alt",settings={ "TNotebook": { "configure": { "tabmargins": [0,5,0],"background": "#ffffff" } },"TNotebook.Tab": { "configure": { "padding": [100,8],"font": ("MS Serif,bold",14) } } }) style.theme_use("MyStyle") # the container is where we'll stack a bunch of frames # on top of each other,then the one we want visible # will be raised above the others container = tk.Frame(self) container.grid() container.grid_rowconfigure(0,weight=1) container.grid_columnconfigure(0,weight=1) self.frames = {} for F in (AutoWindow,ManualWindow): page_name = F.__name__ frame = F(self.start_values,master=container,controller=self,background=background_color) self.frames[page_name] = frame # put all of the pages in the same location; # the one on the top of the stacking order # will be the one that is visible. frame.grid(row=0,column=0,sticky="nsew") if self.mode == "auto": self.show_frame("AutoWindow") elif self.mode == "manual": self.show_frame("ManualWindow") else: raise ValueError("invalid mode format".format(self.mode)) self.toggle_btn = tk.Button(container,text=self.mode,width=12,command=self.toggle) self.toggle_btn.grid() def show_frame(self,page_name,state_values=None): """Show a frame for the given page name""" frame = self.frames[page_name] frame.tkraise() def end_fullscreen(self,event: Union[str,None] = None) -> str: """Toggle full screen""" self.state = False self.attributes("-fullscreen",False) return "break" def toggle(self): """ Get and set the present state of the toggle button """ if self.toggle_btn.config('text')[-1] == 'manual': self.toggle_btn.config(text='auto') self.current_state = "auto" return self.current_state else: self.toggle_btn.config(text='manual') self.current_state = "manual" return self.current_state class ManualWindow(tk.Frame): """The entry window for the GUI Args: master: The main GUI **kwargs: Tkinter's Frame method takes keyword arguments """ def __init__(self,start_values,master: Union[Tparent,None] = None,controller: Union[TMaster,**kwargs): self.frame = tk.Frame.__init__(self,master) self.controller = controller self.start_values = start_values.copy() for key in ['segment','step']: self.start_values.pop(key) self.current_state = "manual" self.setpoint = self.start_values self.bind("<Return>",self.fetch_values) # Input fields namelbl = tk.Label( self,text=name,30),pady=25) namelbl.grid() input_fields = tk.Frame(self,background=background_color) input_fields.grid() for idx,(field,initVal) in enumerate(self.start_values.items()): Entry(input_fields,field,initVal,idx) # Buttons self.set_button = tk.Button(self,text='Set Values',command=self.fetch_values,**button_opts) self.set_button.grid() def fetch_values(self,event=None): """Fetching input entries""" data = dict(elem.get() for elem in Entry.instances) self.setpoint = data print("values set") def switch_frame(self,state_values,event=None): """update entries before switching""" ordered = OrderedDict((k,state_values['setpoint'][k]) for k in list(self.start_values.keys())) # Update the entries for idx,val) in enumerate(dict(ordered).items()): if Entry.instances[idx].ent.state == "disabled": Entry.instances[idx].ent.state = "normal" Entry.instances[idx].ent.delete('0','end') Entry.instances[idx].ent.insert(tk.END,"{:.2f}".format(float(val))) super().tkraise() super().grid() 中遇到错误,因为您的createStore(reducer,enhancer)不适合类型reducer。您必须使减速器适合这种类型。现在的问题是您的减速器不允许(state: State | undefined,action: AnyAction) => Statestate

更改

undefined

const rootReducer = (state: State,action: AnyAction) => {
  1. const rootReducer = (state: State | undefined,action: AnyAction): State => { 行会出现错误,因为redux创建的store.sagaTask = sagaMiddleware.run(rootSaga);对象没有名为store的属性。关于该here的另一讨论。

这是一个基于next-redux-wrapper文档的解决方案:

为商店定义一个包含任务的新界面

sagaTask

替换

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();
,

我在尝试以适当的方式将 Redux 与 Next 同步时也遇到了一些麻烦,他们使用 next-redux-wrapper 创建了一个项目模板,该模板目前正在工作并遵循 next- redux 包装器。你可以看看:

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(
    ({}) => {
    }
);

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...