Next.jsでReactNを使う
3行で言えば
コンポーネントのマウントの前に1回だけグローバル状態の初期化をしたい
ので、1回だけ初期化を実行する高階コンポーネント(HOC)を使って初期化を行う。 In some cases (such as when using Next.js), you may be unable to run a setup script prior to your ReactN components mounting. In order to instantiate your global state and reducers prior to mounting, you may use the withInit Higher Order Component. This HOC will await the setting of your global state before mounting the provided Lower Order Component (e.g. <App />). Next.jsのコードジェネレータが作ったコード_app.tsxはこんな感じ
code:_app.tsx
import '../styles/globals.css'
import type { AppProps } from 'next/app'
function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}
export default MyApp
これに高階コンポーネントwithInitをつける。
READMEのサンプルは下記のようになっているが
型情報がない
コンポーネントが引数を取らない
という点でそのまま_app.tsxに適用できない。
code:ts
import React, { useDispatch, useGlobal, withInit } from 'reactn';
const INITIAL_REDUCERS = {
addOne: ({ count }) => ({
count: count + 1,
}),
};
const INITIAL_STATE = {
count: 0,
};
export default withInit(
INITIAL_STATE,
INITIAL_REDUCERS
)(function App() {
const addOne = useDispatch('addOne');
const count = useGlobal('count'); return <button onClick={addOne}>Count: {count}</button>;
});
ソースを読んで確認したけども、3番目の型引数でコンポーネントの引数の型を受け取っていた。なのでそこに適切に渡してやればOK。
TypeScriptで使うときのためのdeclareもする。
code:_app.tsx
import "../styles/globals.css";
import type { AppProps } from "next/app";
import React, { withInit } from "reactn";
const INITIAL_STATE = {
count: 0,
};
type TYPE_STATE = typeof INITIAL_STATE;
const INITIAL_REDUCERS = {
addOne: ({ count }: TYPE_STATE) => ({
count: count + 1,
}),
};
type TYPE_REDUCERS = typeof INITIAL_REDUCERS;
declare module "reactn/default" {
export interface State extends TYPE_STATE {}
export interface Reducers extends TYPE_REDUCERS {}
}
const MyApp = withInit<TYPE_STATE, TYPE_REDUCERS, AppProps>(
INITIAL_STATE,
INITIAL_REDUCERS
)(({ Component, pageProps }: AppProps) => {
return <Component {...pageProps} />;
});
export default MyApp;