Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/weyheyhey/effector-next
☄️ Effector wrappers for Next.js
https://github.com/weyheyhey/effector-next
effector nextjs react
Last synced: 3 months ago
JSON representation
☄️ Effector wrappers for Next.js
- Host: GitHub
- URL: https://github.com/weyheyhey/effector-next
- Owner: effector
- Archived: true
- Created: 2020-02-24T15:22:54.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2023-04-07T10:59:58.000Z (over 1 year ago)
- Last Synced: 2024-04-14T04:20:08.815Z (7 months ago)
- Topics: effector, nextjs, react
- Language: TypeScript
- Homepage:
- Size: 413 KB
- Stars: 44
- Watchers: 15
- Forks: 6
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Effector Next
> Note: we recommend using [`@effector/next`](https://github.com/effector/next) package.
A HOCs that brings Effector and Next.js together
[![npm version](https://badge.fury.io/js/effector-next.svg)](https://www.npmjs.com/package/effector-next)
## Installation
```bash
npm install effector-next
```or yarn
```bash
yarn add effector-next
```**effector-next** requires `effector`, `effector-react` to be installed
**effector/babel-plugin** is necessary if you do not want to manually name the units
## Settings
1. To load the initial state on the server, you must attach `withFork` wrapper to your `_document` component
pages/_document.jsx```jsx
import Document from "next/document";
import { withFork } from "effector-next";const enhance = withFork({ debug: false });
export default enhance(Document);
```
2. To get the initial state on the client and drop it into the application, you must attach `withHydrate` wrapper to your `_app` component
pages/_app.jsx```jsx
import { withHydrate } from "effector-next";
import App from "next/app";const enhance = withHydrate();
export default enhance(App);
```
3. To bind events/stores on the server to the scope, add aliases from `effector-react` to `effector-react/ssr` in `next.config.js`
next.config.js```js
const { withEffectorReactAliases } = require("effector-next/tools");const enhance = withEffectorReactAliases();
module.exports = enhance({});
```
4. Replace imports from `"effector"` to `"effector-next"`
```diff
- import { createEvent, forward } from "effector"
+ import { createEvent, forward } from "effector-next"
```5. Connect the `effector/babel-plugin`
.babelrc```json
{
"presets": ["next/babel"],
"plugins": ["effector/babel-plugin"]
}
```If you are using `effector` version > 21.3.0, you also need to configure the babel plugin:
```json
{
"presets": ["next/babel"],
"plugins": ["effector/babel-plugin", { "importName": ["effector-next"] }]
}
```
6. Configure what event will be triggered when the page is requested from the server using `withStart`
pages/index.js```jsx
import React from "react";
import { withStart } from "effector-next";
import { useStore } from "effector-react";import { pageLoaded } from "../model";
const enhance = withStart(pageLoaded);
function HomePage() {
return (
Hello World
);
}export default enhance(HomePage);
```
### Example
1. Declare our model
models/index.js```jsx
import { forward, createEvent, createStore, createEffect } from "effector-next";export const pageLoaded = createEvent();
export const buttonClicked = createEvent();const effect = createEffect({
handler(name) {
return Promise.resolve({ name });
},
});export const $data = createStore(null);
$data.on(effect.done, (_, { result }) => result);
forward({
from: pageLoaded.map(() => "nameFromPageLoaded"),
to: effect,
});forward({
from: buttonClicked.map(() => "nameFromButtonClicked"),
to: effect,
});
```
2. Connect the page to the store (all units must be wrapped in hooks - this is necessary in order to associate units with scope on the server)
pages/index.jsx```jsx
import React from "react";
import { useStore, useEvent } from "effector-react";import { $data, buttonClicked } from "../models";
export default function HomePage() {
const data = useStore($data);
const handleClick = useEvent(buttonClicked);return (
HomePage
Store state: {JSON.stringify({ data })}
click to change store state
);
}
```
3. Bind an event that will be called on the server when the page is requested
pages/index.jsx```diff
import React from "react";
import { useStore, useEvent } from "effector-react";
+import { withStart } from "effector-next";-import { $data, buttonClicked } from "../models";
+import { $data, pageLoaded, buttonClicked } from "../models";+const enhance = withStart(pageLoaded);
-export default function HomePage() {
+function HomePage() {
const data = useStore($data);
const handleClick = useEvent(buttonClicked);return (
HomePage
Store state: {JSON.stringify({ data })}
click to change store state
);
}+export default enhance(HomePage);
```
## Configuration
The `withFork` accepts a config object as a parameter:
- `debug` (optional, boolean) : enable debug logging
- `serializeIgnore` (optional, array) : stores whose values should not be sent to the client after serialization## Server payload
When the unit passed to `withStart` is called, the object will be passed as a payload:
- `req` : incoming request
- `res` : serever response
- `cookies` : parsed cookies
- `pathname` : path section of `URL`
- `query` : query string section of `URL` parsed as an object.## Release process
1. Check out the [draft release](https://github.com/effector/nextjs/releases).
1. All PRs should have correct labels and useful titles. You can [review available labels here](https://github.com/effector/nextjs/blob/master/.github/release-drafter.yml).
1. Update labels for PRs and titles, next [manually run the release drafter action](https://github.com/effector/nextjs/actions/workflows/release-drafter.yml) to regenerate the draft release.
1. Review the new version and press "Publish"
1. If required check "Create discussion for this release"