Unstable selectors causes infinite loop in React
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 35/100
- Tipo di issue
- Bug
- Chiarezza
- Da chiarire
- Stato di attività
- Ferma
- Stack tecnologico
- react, typescript
- Ambito
- frontend
Direzione di ricerca
Start by reading src/components/connect.tsx and src/connect/selectorFactory.ts, then compare their memoization with the stability check in src/hooks/useSelector.ts. Reproduce the unstable-selector behavior if possible and review the linked React useSyncExternalStore check. Done means the reported infinite-update case is addressed and connect has a defined stability behavior.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
What version of React, ReactDOM/React Native, Redux, and React Redux are you using?
- React: 18.2.0
- ReactDOM/React Native: 18.2.0
- Redux: 3.7.2 (I know)
- React Redux: 8.1.3
What is the current behavior?
React-redux provides an extra option to check selector stability, but that check:
- has to be explicitly enabled
- is not covering
connectfunction - is a subject of a design flaw
The problem is that selector stability must be enforced
What is the expected behavior?
Redux hard breaks for unstable selectors.
Let me explain problem in details.
Recently we started migration from React-redux v5 to v8. The process was almost frictionless, but later we started experiencing product outages (full or partial page crashes) due to endless updates somewhere deep in React.
One of the problems here - while debugging in production was always letting us find and eliminate the problem, we were never able to reproduce it in unit (jest) or integration(Cypress) tests.
Long story short - every time the problem leading to a crash was unstable mapStateToProps that was one way or another creating endless update loop in React.
Lets check the docs:
a selector that returns a different result reference when called again with the same inputs will cause unnecessary rerenders.... causes the component to rerender after every action is dispatched
– https://react-redux.js.org/api/hooks#selector-result-stability
This description is matching react-redux v5 behavior and is different in v8 due to useSyncExternalStore used underneath. The expected behavior comes from this underlaying hook:
React will re-render the component if getSnapshot return value is different from the last time. This is why, if you always return a different value, you will enter an infinite loop and get this error.
– https://react.dev/reference/react/useSyncExternalStore#im-getting-an-error-the-result-of-getsnapshot-should-be-cached
➡️ In our experience we are getting into infinite loop, but are NOT getting this error.
In fact - React has a "double render"-based check for getSnapshot stability, but react-redux effectively bypasses it via memoization here and here
The outcome of the problem is the following:
connectfunction is missingstabilityCheck. It's not as ease to implement as it was done for useSelector, but this gap should be closed- due to internal implementation of
useSyncExternalStore- stability MUST BE enforced, or React can enter endless loops due to various but yet unknown reasons. useSelectordont have any extra caching layers, and yet the necessity to enforce stability is somewhat unclear. Really wondering why you had to implementstabilityCheckwhile React should detect the absence of memoization and at least throw an error.
Which browser and OS are affected by this issue?
No response
Did this work in previous versions of React Redux?
- Yes
- Lingua principale
- TypeScript
- Stelle
- 23.4k
- Fork
- 3.3k
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di reduxjs/react-redux
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
reduxjs/react-redux#2416 · 1 commento ·
-
Breaking Change Tooling
Difficoltà 5/5 Più di una settimana Idoneità per principianti 15/100
reduxjs/react-redux#2415 ·
-
feat!: remove `alternate-renderers` entry point for v10Forse già presa @aryaemami59 l’ha presa 135 giorni fa. ApertaBreaking Change
reduxjs/react-redux#2336 · 1 reazione · 1 assegnatario ·
-
Performance
Difficoltà 5/5 Più di una settimana Idoneità per principianti 25/100
reduxjs/react-redux#2086 · 16 commenti · 2 reazioni ·
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 35/100
reduxjs/react-redux#2060 · 2 commenti · 1 reazione ·
Tutte le issue di reduxjs/react-redux
Issue simili
-
idea-scout idea:453
Difficoltà 2/5 1-3 ore Idoneità per principianti 83/100
jeanibarz/agent-notebook#453 ·
I maintainer di solito rispondono entro 1 giorno
-
level/task
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 95/100
wazuh/wazuh-dashboard-plugins#9642 ·
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 91/100
unicef/adt-studio#1112 ·
I maintainer di solito rispondono entro 2 giorni
-
feature request good first issue
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
TabularisDB/tabularis#1513 ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 75/100