Skip to content

Commit 885b42c

Browse files
authored
Merge pull request #34 from udecode/perf/set-timeout
2 parents f8b2222 + 7bfe748 commit 885b42c

File tree

5 files changed

+7
-59
lines changed

5 files changed

+7
-59
lines changed

.changeset/shiny-spiders-swim.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'jotai-x': patch
3+
---
4+
5+
PERF: Remove infinite render detection (causing performance issues in development)

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ const { useUserValue, useUserSet, useUserState, UserProvider } =
8585
// Optional derived atoms
8686
intro: atom((get) => `My name is ${get(atoms.name)}`),
8787
}),
88-
infiniteRenderDetectionLimit: 100, // Optional render detection limit
8988
}
9089
);
9190
```
@@ -98,7 +97,6 @@ Available options:
9897
delay?: number;
9998
effect?: React.ComponentType;
10099
extend?: (atoms: Atoms) => DerivedAtoms;
101-
infiniteRenderDetectionLimit?: number;
102100
}
103101
```
104102

@@ -390,7 +388,7 @@ The store-based atom hooks provide more flexibility when working with external a
390388

391389
## Troubleshooting
392390

393-
### Infinite Render Detection
391+
### Infinite Renders
394392

395393
When using value hooks with selectors, ensure they are memoized:
396394

packages/jotai-x/README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ const { useUserValue, useUserSet, useUserState, UserProvider } =
8585
// Optional derived atoms
8686
intro: atom((get) => `My name is ${get(atoms.name)}`),
8787
}),
88-
infiniteRenderDetectionLimit: 100, // Optional render detection limit
8988
}
9089
);
9190
```
@@ -98,7 +97,6 @@ Available options:
9897
delay?: number;
9998
effect?: React.ComponentType;
10099
extend?: (atoms: Atoms) => DerivedAtoms;
101-
infiniteRenderDetectionLimit?: number;
102100
}
103101
```
104102

@@ -390,7 +388,7 @@ The store-based atom hooks provide more flexibility when working with external a
390388

391389
## Troubleshooting
392390

393-
### Infinite Render Detection
391+
### Infinite Renders
394392

395393
When using value hooks with selectors, ensure they are memoized:
396394

packages/jotai-x/src/createAtomStore.spec.tsx

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -142,16 +142,6 @@ describe('createAtomStore', () => {
142142
);
143143
};
144144

145-
const BadSelectorRenderer = () => {
146-
const arr0 = useMyTestStoreStore().useArrValue((v) => v[0]);
147-
return <div>{arr0}</div>;
148-
};
149-
150-
const BadSelectorRenderer2 = () => {
151-
const arr0 = useMyTestStoreValue('arr', { selector: (v) => v[0] });
152-
return <div>{arr0}</div>;
153-
};
154-
155145
const Buttons = () => {
156146
const store = useMyTestStoreStore();
157147
return (
@@ -268,26 +258,6 @@ describe('createAtomStore', () => {
268258
expect(getByText('arrNum: ava')).toBeInTheDocument();
269259
expect(getByText('arrNumWithDeps: ava')).toBeInTheDocument();
270260
});
271-
272-
it('Throw error if user does not memoize selector', () => {
273-
expect(() =>
274-
render(
275-
<MyTestStoreProvider>
276-
<BadSelectorRenderer />
277-
</MyTestStoreProvider>
278-
)
279-
).toThrow();
280-
});
281-
282-
it('Throw error is user does memoize selector 2', () => {
283-
expect(() =>
284-
render(
285-
<MyTestStoreProvider>
286-
<BadSelectorRenderer2 />
287-
</MyTestStoreProvider>
288-
)
289-
).toThrow();
290-
});
291261
});
292262

293263
describe('single provider', () => {

packages/jotai-x/src/createAtomStore.ts

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,6 @@ export interface CreateAtomStoreOptions<
421421
delay?: UseAtomOptions['delay'];
422422
effect?: React.FC;
423423
extend?: (atomsWithoutExtend: StoreAtomsWithoutExtend<T>) => E;
424-
infiniteRenderDetectionLimit?: number;
425424
suppressWarnings?: boolean;
426425
}
427426

@@ -448,7 +447,6 @@ export const createAtomStore = <
448447
delay: delayRoot,
449448
effect,
450449
extend,
451-
infiniteRenderDetectionLimit = 100_000,
452450
suppressWarnings,
453451
}: CreateAtomStoreOptions<T, E, N>
454452
): AtomStoreApi<T, E, N> => {
@@ -510,8 +508,6 @@ export const createAtomStore = <
510508
return store ?? contextStore;
511509
};
512510

513-
let renderCount = 0;
514-
515511
const useAtomValueWithStore: UseAtomValueFn = (
516512
atomConfig,
517513
store,
@@ -520,25 +516,6 @@ export const createAtomStore = <
520516
equalityFnOrDeps,
521517
deps
522518
) => {
523-
// If selector/equalityFn are not memoized, infinite loop will occur.
524-
if (process.env.NODE_ENV !== 'production' && infiniteRenderDetectionLimit) {
525-
renderCount += 1;
526-
if (renderCount > infiniteRenderDetectionLimit) {
527-
throw new Error(
528-
`
529-
use<Key>Value/useValue/use<StoreName>Value has rendered ${infiniteRenderDetectionLimit} times in the same render.
530-
It is very likely to have fallen into an infinite loop.
531-
That is because you do not memoize the selector/equalityFn function param.
532-
Please wrap them with useCallback or configure the deps array correctly.`
533-
);
534-
}
535-
// We need to use setTimeout instead of useEffect here, because when infinite loop happens,
536-
// the effect (fired in the next micro task) will execute before the rerender.
537-
setTimeout(() => {
538-
renderCount = 0;
539-
});
540-
}
541-
542519
const options = convertScopeShorthand(optionsOrScope);
543520
const equalityFn =
544521
typeof equalityFnOrDeps === 'function' ? equalityFnOrDeps : undefined;

0 commit comments

Comments
 (0)