Integrate Next.js with effector
To do this, we will use the native fork method. In the _app.tsx file, we create our own scope and wrap the application in a provider from effector-react/scope
import { AppProps } from 'next/app';
import { FC } from 'react';
import { Provider } from 'effector-react/scope';
import { fork, Scope, serialize } from 'effector';
let clientScope: Scope;
const App: FC<AppProps<{ initialState }>> = ({ Component, pageProps }) => {
const scope = fork({
values: {
...(clientScope && serialize(clientScope)),
...pageProps.initialState,
},
});
if (typeof window !== 'undefined') {
clientScope = scope;
}
return (
<Provider
key={scope?.graphite?.id || '0'}
value={scope}
>
<Component {...pageProps} />
</Provider>
);
};
export default App;
Next, you need to add .babelrc to the project root with the following content:
{
"plugins": [
[
"effector/babel-plugin", {
"reactSsr": true,
}
]
]
}
You also need to add an alias to next.config.js to avoid build errors, when under the hood it imports, then cjs then mjs files.
config.resolve.alias.effector = path.resolve(__dirname, './node_modules/effector/effector.cjs.js');
config.resolve.alias['effector-react/ssr'] = path.resolve(__dirname, './node_modules/effector-react/ssr.js');
config.resolve.alias['effector-react/scope'] = path.resolve(__dirname, './node_modules/effector-react/scope.js');
config.resolve.alias['effector-react'] = path.resolve(__dirname, './node_modules/effector-react/ssr.js');
For the convenience of development, we add the following rules to our eslint:
module.exports = {
root: true,
extends: [
'effector',
'plugin:effector/react',
'plugin:effector/scope',
'plugin:effector/future',
'plugin:effector/patronum',
'plugin:effector/recommended',
],
rules: {
'no-restricted-imports': [
'error',
{
paths: [
{
name: 'effector-react',
message: "Please import from 'effector-react/scope' instead.",
},
],
},
],
},
};