diff --git a/docs/extending/js-plugin-api.md b/docs/extending/js-plugin-api.md index c1ade265b..8d1a0a330 100644 --- a/docs/extending/js-plugin-api.md +++ b/docs/extending/js-plugin-api.md @@ -68,7 +68,8 @@ Informs the plugin whether or not the client is archived, and therefore not curr Sometimes it's desirable for a plugin to be able to process incoming messages from the client even when inactive. To do this, define a static `persistedStateReducer` function in the plugin class: -``` + +```typescript static persistedStateReducer( persistedState: PersistedState, method: string, @@ -78,6 +79,26 @@ static persistedStateReducer( The job of the `persistedStateReducer` is to merge incoming data into the state, so that next time the plugin is activated, the persisted state will be ready. +The data that is produced from `persistedStateReducer` should be immutable, but also structurally sharing unchanged parts of the state with the previous state to avoid performance hiccups. To simplify this process we recommend using the [Immer](https://immerjs.github.io/immer/docs/introduction) package. +Immer makes it possible to keep the reducer concise by directly supporting "writing" to the current state, and keeping track of that in the background. +Also it will guarantee that there are no accidental data manipulations by freezing the produced state. + +You can directly `import {produce} from "flipper"` so there is no need to add Immer as additional dependency. + +A quick example: + +```typescript +static persistedStateReducer(persistedState, method, data) { + return produce(persistedState, draft => { + if (method.name === "newRecord") { + draft.lastRecordReceived = Date.now(); + draft.records.push(data); + } + }); +} +``` + + ## Notifications Plugins can publish system notifications to alert the user of something. This is particularly useful when the plugin isn't the current active plugin. All notifications are aggregated in Flipper's notifications pane, accessible from the sidebar. diff --git a/package.json b/package.json index 2f31638c0..b8e9fd58f 100644 --- a/package.json +++ b/package.json @@ -138,6 +138,7 @@ "express": "^4.15.2", "flipper-doctor": "^0.2.1", "fs-extra": "^8.0.1", + "immer": "^5.0.1", "immutable": "^4.0.0-rc.12", "invariant": "^2.2.2", "line-replace": "^1.0.2", diff --git a/src/index.tsx b/src/index.tsx index 28f2edde1..751bc4073 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -9,6 +9,8 @@ export {default as styled} from '@emotion/styled'; export {keyframes} from 'emotion'; +export {produce} from 'immer'; + export * from './ui/index'; export {getStringFromErrorLike, textContent, sleep} from './utils/index'; export {serialize, deserialize} from './utils/serialization'; diff --git a/yarn.lock b/yarn.lock index 29175ab27..96841f42a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4708,6 +4708,11 @@ ignore@^5.1.1: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A== +immer@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/immer/-/immer-5.0.1.tgz#1a1184fa758f68f1b5573db840825fb5164cceca" + integrity sha512-KFHV1ivrBmPCVRhjy9oBooypnPfJ876NTrWXMNoUhXFAaWWAViVqZ4l6HxPST52qcN82qqsR38/pCGYRWP5W7w== + immutable@^4.0.0-rc.12: version "4.0.0-rc.12" resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0-rc.12.tgz#ca59a7e4c19ae8d9bf74a97bdf0f6e2f2a5d0217"