├── .eslintrc.json
├── .gitignore
├── .prettierrc
├── LICENSE
├── README.md
├── package.json
├── rollup.config.js
├── src
├── hooks.ts
├── index.ts
├── loops
│ ├── fixed-loop.ts
│ └── render-loop.ts
├── store.ts
├── types.ts
└── update.tsx
└── tsconfig.json
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es2021": true
5 | },
6 | "extends": [
7 | "eslint:recommended",
8 | "plugin:react/recommended",
9 | "plugin:@typescript-eslint/recommended",
10 | "plugin:react-hooks/recommended"
11 | ],
12 | "parser": "@typescript-eslint/parser",
13 | "parserOptions": {
14 | "ecmaFeatures": {
15 | "jsx": true
16 | },
17 | "ecmaVersion": "latest",
18 | "sourceType": "module"
19 | },
20 | "plugins": ["react", "@typescript-eslint"],
21 | "rules": {
22 | "react/display-name": "off",
23 | "@typescript-eslint/no-non-null-assertion": "off",
24 | "@typescript-eslint/no-explicit-any": "off"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | coverage/
3 | dist/
4 | types/
5 | yarn-error.log
6 | .size-snapshot.json
7 | Thumbs.db
8 | ehthumbs.db
9 | Desktop.ini
10 | $RECYCLE.BIN/
11 | .DS_Store
12 | .vscode
13 | .docz/
14 | package-lock.json
15 | coverage/
16 | .idea
17 | .rpt2_cache/
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": true,
3 | "trailingComma": "all",
4 | "singleQuote": true,
5 | "tabWidth": 2,
6 | "printWidth": 120,
7 | "jsxBracketSameLine": true
8 | }
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 krispya
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-three-update
2 |
3 | ### 🚨 Warning: This library has been merged into [react-three-fiber v9](https://github.com/pmndrs/react-three-fiber/tree/v9) and is actively developed there. This repository will remain here only for reference.
4 |
5 |
6 |
7 |
8 | React hooks for Unity-like updates in [react-three-fiber](https://github.com/pmndrs/react-three-fiber).
9 |
10 | ```bash
11 | npm install react-three-update # or yarn add react-three-update
12 | ```
13 |
14 | Unity provides a [strict ordering of events](https://docs.unity3d.com/Manual/ExecutionOrder.html) that many game developers are familiar with. Meanwhile, react-three-fiber only has `useFrame` with priority that is coupled to the frameloop being in manual mode and lacks a fixed update method. react-three-update solves this by extending `useFrame` to have a strict sequence of update hooks along with a fixed frame loop. The updates are executed in the following order: `useEarlyUpdate`, `useFixedUpdate`, `useUpdate`, `useLateUpdate` and then `useRenderUpdate`. It also overrides the default react-three-fiber priority behavior with `useFrame` such that the priority going into positive numbers no longer puts it into manual mode. This means we are gree to set priorities how we like and configure manual mode separately!
15 |
16 | 👉 Note: The default `useFrame` priority aligns with the default update stage (priority of 0). This means Drei components will generally occur during the update stage along with most other business logic.
17 |
18 | ## How it works
19 |
20 | Wrap your game in the Update component and then subscribe your business logic to update events with the hooks.
21 |
22 | ```jsx
23 | import { Canvas } from '@react-three/fiber';
24 | import { Update, useEarlyUpdate, useFixedUpdate, useUpdate, useLateUpdate, useRenderUpdate } from 'react-three-update';
25 |
26 | function App() {
27 | return (
28 |
33 | );
34 | }
35 |
36 | function Game() {
37 | useEarlyUpdate((state, delta, fixedState) => {
38 | // Do early updates here like input polling.
39 | });
40 |
41 | useFixedUpdate((state, fixedStep, fixedState) => {
42 | // Updates on a fixed step happen here. This is often physics
43 | // and mutations that need to be deterministic.
44 | // physics.step(fixedStep);
45 | });
46 |
47 | useUpdate((state, delta, fixedState) => {
48 | // The bulk of your business logic will go here.
49 | });
50 |
51 | useLateUpdate((state, delta, fixedState) => {
52 | // Any updates you want to occur right before rendering.
53 | // For example having a camera follow a character who might
54 | // be moved by input, physics or other interactions.
55 | });
56 |
57 | useRenderUpdate((state, delta, fixedState) => {
58 | // These updates happen during the rendering stage such as for
59 | // postprocessing. You can use an optional second paramter to define
60 | // a render function to be run at the end. Combine this with
61 | // frameloop={{ manual: true }} on Update.
62 | }, isRenderFunc);
63 |
64 | return {
65 | /* children */
66 | };
67 | }
68 | ```
69 |
70 | ## More about `useRenderUpdate` and manual mode
71 |
72 | R3F no longer relies on the `useFrame` priority to infer when the frameloop goes into manual mode when using react-three-update. This is true even if you are invoking `useFrame` directly. In order to use manual mode, you can set `frameloop` on `Update`. If undefined, the default `Canvas` properties are used instead.
73 |
74 | ```tsx
75 |
76 | ```
77 |
78 | You will need to invoke a render function manually, either from R3F or from a prostprocessing library. [See here for more](https://docs.pmnd.rs/react-three-fiber/api/hooks#taking-over-the-render-loop). You can tell react-three-update which invocation of `useRenderUpdate` is meant to be the render function (and therefore called last) with an optional second parameter. When set to true, that function will be run last.
79 |
80 | ```jsx
81 | useRenderUpdate(({ gl, scene, camera }) => gl.render(scene, camera), true);
82 | ```
83 |
84 | ## More about `useFixedUpdate`
85 |
86 | There is a single fixed update loop that any callback passed into `useFixedUpdate` subscribes to. You can set the `fixedStep` and `maxSubsteps` on `Update`.
87 |
88 | ```jsx
89 |
90 | ```
91 |
92 | | Prop | Description | Type | Default |
93 | | ------------- | ----------------------------------------------------------------------------------------------------------------- | -------- | ------- |
94 | | `fixedStep` | The rate of the fixed update. 1/60 is 60 frames per second. | `number` | `1/50` |
95 | | `maxSubsteps` | The maximum amount of substeps before the loop bails. Only relevant when the framerate drops below the step size. | `number` | `10` |
96 |
97 | 👉 Note: These properties can be updated dynamically during runtime.
98 |
99 | ### Accessing the fixedState
100 |
101 | A `fixedState` can be accessed from any update hook.
102 |
103 | ```jsx
104 | useUpdate((state, delta, fixedState) => { const factor = fixedState.factor }
105 | ```
106 |
107 | And has the following properties:
108 | | Prop | Description | Type |
109 | | ------------- | ----------------------------------------------------------------------------------------------------------------- | -------- |
110 | | `fixedStep` | The rate of the fixed update. 1/60 is 60 frames per second. | `number` |
111 | | `maxSubsteps` | The maximum amount of substeps before the loop bails. Only relevant when the framerate drops below the step size. | `number` |
112 | | `remainder` | The time remaining after a fixed loop is complete. See [Fix Your Step](https://gafferongames.com/post/fix_your_timestep#the-final-touch). | `number` |
113 | | `factor` | The interpolation factor. Calculated by `remainder / fixedStep`. See [Fix Your Step](https://gafferongames.com/post/fix_your_timestep#the-final-touch). | `number` |
114 |
115 | This can be useful for manually implementing interpolation for physics or other effects that rely on a fixed update.
116 |
117 | ## Imperative updates with useUpdateApi
118 |
119 | You can update the fixed update state imperatively with `useUpdateApi`. Like `useThree`, the hook is reactive and accepts selectors. You can access the fixed or render state.
120 |
121 | ```jsx
122 | import { useUpdateApi } from 'react-three-update'
123 |
124 | // For full state.
125 | function Foo() {
126 | const state = useUpdateApi()
127 | ...
128 |
129 | // Or with selector.
130 | function Foo() {
131 | const setFixedStep = useUpdateApi((state) => state.fixed.setFixedStep);
132 | ...
133 | ```
134 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-three-update",
3 | "version": "0.4.0",
4 | "description": "⏱ Unity-like updates for react-three-fiber",
5 | "main": "dist/react-three-update.cjs.js",
6 | "module": "dist/react-three-update.esm.js",
7 | "types": "dist/types/index.d.ts",
8 | "scripts": {
9 | "build": "tsc && rollup -c",
10 | "test": "echo tests are missing",
11 | "pretest": "npm run build"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "git+https://github.com/krispya/react-three-update.git"
16 | },
17 | "author": "Kris Baumgartner",
18 | "license": "MIT",
19 | "bugs": {
20 | "url": "https://github.com/krispya/react-three-update/issues"
21 | },
22 | "homepage": "https://github.com/krispya/react-three-update#readme",
23 | "dependencies": {
24 | "zustand": "^3.7.2"
25 | },
26 | "peerDependencies": {
27 | "@react-three/fiber": ">=8.0",
28 | "react": ">=18.0",
29 | "three": ">=0.139"
30 | },
31 | "devDependencies": {
32 | "@babel/core": "^7.17.9",
33 | "@babel/plugin-transform-runtime": "^7.17.0",
34 | "@babel/preset-env": "^7.16.11",
35 | "@babel/preset-react": "^7.16.7",
36 | "@babel/preset-typescript": "^7.16.7",
37 | "@rollup/plugin-babel": "^5.3.1",
38 | "@rollup/plugin-node-resolve": "^13.2.1",
39 | "@types/three": "^0.139.0",
40 | "@typescript-eslint/eslint-plugin": "^5.22.0",
41 | "@typescript-eslint/parser": "^5.22.0",
42 | "eslint": "^8.15.0",
43 | "eslint-plugin-react": "^7.29.4",
44 | "eslint-plugin-react-hooks": "^4.5.0",
45 | "jest": "^27.5.1",
46 | "rollup": "^2.70.1",
47 | "typescript": "^4.6.4"
48 | },
49 | "files": [
50 | "dist",
51 | "src"
52 | ]
53 | }
54 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import babel from '@rollup/plugin-babel';
2 | import pkg from './package.json';
3 | import pluginNodeResolve from '@rollup/plugin-node-resolve';
4 |
5 | // These are our dependencies, everything else is in the bundle
6 | const external = ['@react-three/fiber', 'react', 'react/jsx-runtime', 'three'];
7 | const extensions = ['.js', '.jsx', '.ts', '.tsx', '.json'];
8 |
9 | const getBabelOptions = ({ useESModules }, targets) => ({
10 | babelHelpers: 'runtime',
11 | babelrc: false,
12 | extensions,
13 | include: ['src/**/*', '**/node_modules/**'],
14 | plugins: [['@babel/transform-runtime', { regenerator: false, useESModules }]],
15 | presets: [
16 | ['@babel/preset-env', { loose: true, modules: false, targets }],
17 | '@babel/preset-react',
18 | '@babel/preset-typescript',
19 | ],
20 | });
21 |
22 | export default [
23 | {
24 | external,
25 | input: 'src/index.ts',
26 | output: [
27 | { file: pkg.main, format: 'cjs' },
28 | { file: pkg.module, format: 'es' },
29 | ],
30 | plugins: [
31 | pluginNodeResolve({ extensions }),
32 | babel(getBabelOptions({ useESModules: true }, '>1%, not dead, not ie 11, not op_mini all')),
33 | ],
34 | },
35 | ];
36 |
--------------------------------------------------------------------------------
/src/hooks.ts:
--------------------------------------------------------------------------------
1 | import { useFrame } from '@react-three/fiber';
2 | import { useLayoutEffect, useRef } from 'react';
3 | import { FixedCallback, RenderCallback, UpdateCallback } from './types';
4 | import { useStoreApi } from './store';
5 |
6 | export enum stage {
7 | early = -200,
8 | fixed = -100,
9 | default = 0,
10 | late = 100,
11 | render = 200,
12 | }
13 |
14 | export function useEarlyUpdate(callback: UpdateCallback) {
15 | const store = useStoreApi();
16 | useFrame((state, delta, frame) => {
17 | callback(state, delta, store.getState().fixed, frame);
18 | }, stage.early);
19 | }
20 |
21 | export function useFixedUpdate(callback: FixedCallback) {
22 | const subscribe = useStoreApi().getState().fixed.subscribe;
23 | const ref = useRef(callback);
24 | useLayoutEffect(() => subscribe(ref), [subscribe]);
25 | }
26 |
27 | export function useUpdate(callback: UpdateCallback) {
28 | const store = useStoreApi();
29 | useFrame((state, delta, frame) => {
30 | callback(state, delta, store.getState().fixed, frame);
31 | }, stage.default);
32 | }
33 |
34 | export function useLateUpdate(callback: UpdateCallback) {
35 | const store = useStoreApi();
36 | useFrame((state, delta, frame) => {
37 | callback(state, delta, store.getState().fixed, frame);
38 | }, stage.late);
39 | }
40 |
41 | export function useRenderUpdate(callback: RenderCallback, priority?: number) {
42 | const subscribe = useStoreApi().getState().render.subscribe;
43 | const ref = useRef(callback);
44 | useLayoutEffect(() => subscribe(ref, priority ?? 0), [priority, subscribe]);
45 | }
46 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export { useEarlyUpdate, useFixedUpdate, useUpdate, useLateUpdate, useRenderUpdate, stage } from './hooks';
2 | export { Update } from './update';
3 | export { useUpdateApi } from './store';
4 |
--------------------------------------------------------------------------------
/src/loops/fixed-loop.ts:
--------------------------------------------------------------------------------
1 | import { useFrame } from '@react-three/fiber';
2 | import { FixedSubscription } from '../types';
3 | import { stage } from '../hooks';
4 | import { useStoreApi } from '../store';
5 |
6 | let subscribers: FixedSubscription[];
7 | let subscription: FixedSubscription;
8 | let fixedStep: number;
9 | let maxSubsteps: number;
10 |
11 | export function useFixedLoop() {
12 | let accumulator = 0;
13 | const store = useStoreApi();
14 |
15 | useFrame((state, delta) => {
16 | const fixedState = store.getState().fixed;
17 | fixedStep = fixedState.fixedStep;
18 | subscribers = fixedState.subscribers;
19 | maxSubsteps = fixedState.maxSubsteps;
20 |
21 | accumulator += delta;
22 | const initialTime = performance.now();
23 | let substeps = 0;
24 |
25 | while (accumulator >= fixedStep && substeps < maxSubsteps) {
26 | accumulator -= fixedStep;
27 | substeps++;
28 |
29 | for (let i = 0; i < subscribers.length; i++) {
30 | subscription = subscribers[i];
31 | subscription.current(state, fixedStep, fixedState);
32 | }
33 |
34 | if (performance.now() - initialTime > fixedStep * 1000) {
35 | // The framerate is not interactive anymore. Better bail out.
36 | break;
37 | }
38 | }
39 |
40 | // If the accumulator is bigger than delta, set it to 1.
41 | // It should never be bigger than delta unless something went wrong.
42 | accumulator = accumulator % fixedStep;
43 |
44 | const factor = accumulator / fixedStep;
45 | store.setState(({ fixed }) => ({ fixed: { ...fixed, factor: factor, remainder: accumulator } }));
46 | }, stage.fixed);
47 | }
48 |
--------------------------------------------------------------------------------
/src/loops/render-loop.ts:
--------------------------------------------------------------------------------
1 | import { useFrame } from '@react-three/fiber';
2 | import { useStoreApi } from '../store';
3 | import { stage } from '../hooks';
4 | import { Subscription, RenderCallbackRef } from 'types';
5 |
6 | let subscription: Subscription;
7 |
8 | export function useRenderLoop() {
9 | const store = useStoreApi();
10 |
11 | useFrame((state, delta) => {
12 | const renderState = store.getState().render;
13 | const fixedState = store.getState().fixed;
14 | const { subscribers } = renderState;
15 |
16 | for (let i = 0; i < subscribers.length; i++) {
17 | subscription = subscribers[i];
18 | subscription.ref.current(state, delta, fixedState);
19 | }
20 | }, stage.render);
21 | }
22 |
--------------------------------------------------------------------------------
/src/store.ts:
--------------------------------------------------------------------------------
1 | import createContext from 'zustand/context';
2 | import { subscribeWithSelector } from 'zustand/middleware';
3 | import create from 'zustand';
4 | import { FixedSubscription, RenderCallbackRef, RenderOptions, UpdateSelector, UpdateState } from './types';
5 |
6 | export const { Provider, useStore, useStoreApi } = createContext();
7 | export const createStore = (fixedStep: number, maxSubsteps: number, render?: RenderOptions) => () =>
8 | create(
9 | subscribeWithSelector((set) => ({
10 | // Fixed update state
11 | fixed: {
12 | fixedStep: fixedStep,
13 | maxSubsteps: maxSubsteps,
14 | factor: 0,
15 | remainder: 0,
16 | subscribers: [] as FixedSubscription[],
17 | subscribe: (ref: FixedSubscription) => {
18 | set(({ fixed }) => ({
19 | fixed: { ...fixed, subscribers: [...fixed.subscribers, ref] },
20 | }));
21 | return () => {
22 | set(({ fixed }) => ({
23 | fixed: {
24 | ...fixed,
25 | subscribers: fixed.subscribers.filter((s) => s !== ref),
26 | },
27 | }));
28 | };
29 | },
30 |
31 | setFixedStep: (v: number) => set(({ fixed }) => ({ fixed: { ...fixed, fixedStep: v } })),
32 | setMaxSubsteps: (v: number) => set(({ fixed }) => ({ fixed: { ...fixed, maxSubsteps: v } })),
33 | },
34 | // Render update state
35 | render: {
36 | render: render,
37 | setRender: (v?: RenderOptions) => set(({ render }) => ({ render: { ...render, render: v } })),
38 | subscribers: [],
39 | subscribe: (ref: RenderCallbackRef, priority: number) => {
40 | set(({ render }) => ({
41 | render: {
42 | ...render,
43 | subscribers: [...render.subscribers, { ref, priority }].sort((a, b) => a.priority - b.priority),
44 | },
45 | }));
46 | return () => {
47 | set(({ render }) => ({
48 | render: {
49 | ...render,
50 | subscribers: render.subscribers.filter((s) => s.ref !== ref),
51 | },
52 | }));
53 | };
54 | },
55 | },
56 | })),
57 | );
58 |
59 | export const useUpdateApi = (selector: UpdateSelector) => useStore(selector);
60 |
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | import { RootState } from '@react-three/fiber';
2 | import { MutableRefObject } from 'react';
3 | import { StateSelector } from 'zustand';
4 |
5 | export type RenderOptions = 'auto' | 'demand';
6 |
7 | export type UpdateProps = {
8 | render?: RenderOptions;
9 | fixedStep?: number;
10 | maxSubsteps?: number;
11 | children: React.ReactElement;
12 | };
13 |
14 | export type ConfigureProps = Omit;
15 |
16 | export interface UpdateCallback {
17 | (state: RootState, delta: number, fixedState: FixedState, frame?: THREE.XRFrame): void;
18 | }
19 | export interface FixedCallback {
20 | (state: RootState, fixedStep: number, fixedState: FixedState, frame?: THREE.XRFrame): void;
21 | }
22 | export interface RenderCallback {
23 | (state: RootState, delta: number, fixedState: FixedState, frame?: THREE.XRFrame): void;
24 | }
25 |
26 | export type FixedCallbackRef = MutableRefObject;
27 | export type RenderCallbackRef = MutableRefObject;
28 |
29 | export type FixedSubscription = FixedCallbackRef;
30 | export type Subscription = {
31 | ref: T;
32 | priority: number;
33 | };
34 |
35 | export type FixedState = {
36 | fixedStep: number;
37 | maxSubsteps: number;
38 | factor: number;
39 | remainder: number;
40 | subscribers: FixedSubscription[];
41 | subscribe: (ref: FixedSubscription) => () => void;
42 | setFixedStep: (v: number) => void;
43 | setMaxSubsteps: (v: number) => void;
44 | };
45 |
46 | export type FixedSlice = {
47 | fixed: FixedState;
48 | };
49 |
50 | export type RenderState = {
51 | render?: RenderOptions;
52 | setRender: (v?: RenderOptions) => void;
53 | subscribers: Subscription[];
54 | subscribe: (ref: RenderCallbackRef, priority: number) => () => void;
55 | };
56 |
57 | export type RenderSlice = {
58 | render: RenderState;
59 | };
60 |
61 | export type UpdateState = FixedSlice & RenderSlice;
62 | export type UpdateSelector = StateSelector>;
63 |
--------------------------------------------------------------------------------
/src/update.tsx:
--------------------------------------------------------------------------------
1 | import React, { useLayoutEffect, useMemo } from 'react';
2 | import { Provider, createStore, useStoreApi } from './store';
3 | import { useFixedLoop } from './loops/fixed-loop';
4 | import { useRenderLoop } from './loops/render-loop';
5 | import { ConfigureProps, UpdateProps } from './types';
6 | import { useStore as useStoreR3F } from '@react-three/fiber';
7 |
8 | export const Update = React.memo(({ fixedStep = 1 / 50, maxSubsteps = 10, render, children }: UpdateProps) => {
9 | return (
10 |
11 |
12 | {children}
13 |
14 |
15 | );
16 | });
17 |
18 | function Configure({ fixedStep, maxSubsteps, render }: ConfigureProps) {
19 | const storeR3F = useStoreApi();
20 | const fixedState = storeR3F.getState().fixed;
21 | const renderState = storeR3F.getState().render;
22 |
23 | fixedState.setFixedStep(fixedStep!);
24 | fixedState.setMaxSubsteps(maxSubsteps!);
25 | renderState.setRender(render);
26 |
27 | return null;
28 | }
29 |
30 | function Loop({ children }: { children: React.ReactElement }) {
31 | useFixedLoop();
32 | useRenderLoop();
33 | return children;
34 | }
35 |
36 | // Credits to Cody Bennett for this brilliant workaround.
37 | // https://codesandbox.io/s/summer-glitter-3lirnp
38 | function FrameOverrides() {
39 | const storeR3F = useStoreR3F();
40 | const store = useStoreApi();
41 | const render = useMemo(() => store.getState().render.render, [store]);
42 |
43 | const demand = render === 'demand' ? true : false;
44 |
45 | // Stop R3F from calling gl.render with demand
46 | useLayoutEffect(() => {
47 | const overridePriority = (state: any) => {
48 | if (state.internal.priority !== demand) {
49 | state.set(({ internal }: { internal: any }) => ({
50 | internal: { ...internal, priority: demand },
51 | }));
52 | }
53 | };
54 | overridePriority(storeR3F.getState());
55 |
56 | return storeR3F.subscribe(overridePriority);
57 | }, [storeR3F, demand]);
58 |
59 | return null;
60 | }
61 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es6",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "esModuleInterop": true,
8 | "allowSyntheticDefaultImports": true,
9 | "strict": true,
10 | "forceConsistentCasingInFileNames": true,
11 | "noFallthroughCasesInSwitch": true,
12 | "module": "esnext",
13 | "moduleResolution": "node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "jsx": "react-jsx",
17 | "baseUrl": "./src",
18 | "declaration": true,
19 | "emitDeclarationOnly": true,
20 | "declarationDir": "./dist/types"
21 | },
22 | "exclude": ["./node_modules/**/*"],
23 | "include": ["./src"]
24 | }
25 |
--------------------------------------------------------------------------------