From cfd03c652450146ebb1b09ab3787afa64052c3b9 Mon Sep 17 00:00:00 2001 From: Mateusz Titz Date: Wed, 28 Aug 2024 13:39:59 +0200 Subject: [PATCH 1/3] Add docs describing react strict mode in detail --- README.md | 1 + contributingGuides/STRICT_MODE.md | 32 +++++++++++++++++++++++++++++++ src/App.tsx | 2 +- src/CONFIG.ts | 3 ++- 4 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 contributingGuides/STRICT_MODE.md diff --git a/README.md b/README.md index c10c954a18646..529d6cb0ccfdb 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ * [Contributing to Expensify](contributingGuides/CONTRIBUTING.md) * [Expensify Code of Conduct](CODE_OF_CONDUCT.md) * [Contributor License Agreement](contributingGuides/CLA.md) +* [React StrictMode](contributingGuides/STRICT_MODE.md) ---- diff --git a/contributingGuides/STRICT_MODE.md b/contributingGuides/STRICT_MODE.md new file mode 100644 index 0000000000000..01bb5faee0437 --- /dev/null +++ b/contributingGuides/STRICT_MODE.md @@ -0,0 +1,32 @@ +# Usage of react concurrent mode and StrictMode +## Concurrent react +This App is rendered using react concurrent mode, which is the direction that React seems to be moving. + +Concurrent mode enables a lot of new behaviours in react, most importantly renders can be interrupted by React, re-run or run more than once. This is supposed to make react more performant and webapps more responsive to user actions. + +Further reading: + - [What is Concurrent React](https://react.dev/blog/2022/03/29/react-v18#what-is-concurrent-react) + +## StrictMode +Because the previously described react mode could potentially introduce new bugs in the code (related to parallel rendering) we are also using ``. +This is a recommendation from React team as per react official docs. + +`` is a component that wraps the whole App in (or parts of App) and it runs extra checks and extra behaviors only in dev. So in essence this is a developer tool. + +### Temporarily disabling StrictMode for dev +Strict mode *by default always* wraps entire Expensify App component tree. This happens in `src/App.tsx`. + +However, it might happen you want to temporarily disable `StrictMode` when developing, to verify that your code behaves properly. + +To do that: + - go to `src/CONFIG.ts` + - set `USE_REACT_STRICT_MODE_IN_DEV` flag to `false` + +_Important note_: this ☝️flag is strictly for developers. It does not affect production builds of React. +StrictMode is supposed to always wrap your App regardless of environment, and it will simply do nothing when run on production react build. +Only use this flag for local development and testing, but do not make it depending on `NODE_ENV` or any other env vars. + +sources: + - [StrictMode docs](https://react.dev/reference/react/StrictMode) + - [StrictMode recommended usage](https://react.dev/reference/react/StrictMode) + - [Original PR introducing this feature](https://github.com/Expensify/App/pull/42592) \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index 98b5d4afeb1d9..4de8269fb4414 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -54,7 +54,7 @@ LogBox.ignoreLogs([ const fill = {flex: 1}; -const StrictModeWrapper = CONFIG.USE_REACT_STRICT_MODE ? React.StrictMode : ({children}: {children: React.ReactElement}) => children; +const StrictModeWrapper = CONFIG.USE_REACT_STRICT_MODE_IN_DEV ? React.StrictMode : ({children}: {children: React.ReactElement}) => children; function App({url}: AppProps) { useDefaultDragAndDrop(); diff --git a/src/CONFIG.ts b/src/CONFIG.ts index 8800cc907588a..a1a72b86fadd6 100644 --- a/src/CONFIG.ts +++ b/src/CONFIG.ts @@ -96,5 +96,6 @@ export default { IOS_CLIENT_ID: '921154746561-s3uqn2oe4m85tufi6mqflbfbuajrm2i3.apps.googleusercontent.com', }, GCP_GEOLOCATION_API_KEY: googleGeolocationAPIKey, - USE_REACT_STRICT_MODE: true, + // to read more about StrictMode see: contributingGuides/STRICT_MODE.md + USE_REACT_STRICT_MODE_IN_DEV: true, } as const; From 966f5bf5c1c9def92be7b1f829f36046456cd3eb Mon Sep 17 00:00:00 2001 From: Mateusz Titz Date: Wed, 28 Aug 2024 15:17:34 +0200 Subject: [PATCH 2/3] update strict mode docs --- contributingGuides/STRICT_MODE.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/contributingGuides/STRICT_MODE.md b/contributingGuides/STRICT_MODE.md index 01bb5faee0437..313b2de4b68e0 100644 --- a/contributingGuides/STRICT_MODE.md +++ b/contributingGuides/STRICT_MODE.md @@ -8,7 +8,7 @@ Further reading: - [What is Concurrent React](https://react.dev/blog/2022/03/29/react-v18#what-is-concurrent-react) ## StrictMode -Because the previously described react mode could potentially introduce new bugs in the code (related to parallel rendering) we are also using ``. +Because the previously described concurrent mode could potentially introduce new bugs in the code (related to parallel rendering) we are using ``. This is a recommendation from React team as per react official docs. `` is a component that wraps the whole App in (or parts of App) and it runs extra checks and extra behaviors only in dev. So in essence this is a developer tool. @@ -26,6 +26,10 @@ _Important note_: this ☝️flag is strictly for developers. It does not affect StrictMode is supposed to always wrap your App regardless of environment, and it will simply do nothing when run on production react build. Only use this flag for local development and testing, but do not make it depending on `NODE_ENV` or any other env vars. +### Common StrictMode pitfalls + - every component will go through: `mount -> unmount -> mount` on first app render + - any code running inside `useEffect(() => {...}, [])` that would be expected to run once on initial render, will run twice, this might include initial api calls + sources: - [StrictMode docs](https://react.dev/reference/react/StrictMode) - [StrictMode recommended usage](https://react.dev/reference/react/StrictMode) From d23e00c00ad53232b67360891cd6ea7ce48e3c35 Mon Sep 17 00:00:00 2001 From: Mateusz Titz Date: Wed, 28 Aug 2024 16:20:35 +0200 Subject: [PATCH 3/3] Improve STRICT_MODE docs --- contributingGuides/STRICT_MODE.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/contributingGuides/STRICT_MODE.md b/contributingGuides/STRICT_MODE.md index 313b2de4b68e0..dfe94ea2c3ba4 100644 --- a/contributingGuides/STRICT_MODE.md +++ b/contributingGuides/STRICT_MODE.md @@ -30,7 +30,15 @@ Only use this flag for local development and testing, but do not make it dependi - every component will go through: `mount -> unmount -> mount` on first app render - any code running inside `useEffect(() => {...}, [])` that would be expected to run once on initial render, will run twice, this might include initial api calls -sources: +#### Example: How StrictMode Affects AuthScreen +In AuthScreen, we have a typical pattern where certain logic is executed during mounting and unmounting, this is what happen after a refresh: +- Mounting: it runs `ReconnectApp`. +- Unmounting: AuthScreen cleans up data. +- Re-mounting Due to StrictMode: This behavior will cause `OpenApp` to be executed on the new mount. + +Impact: This double execution could lead to unnecessary API calls or unexpected states. + +Sources: - [StrictMode docs](https://react.dev/reference/react/StrictMode) - [StrictMode recommended usage](https://react.dev/reference/react/StrictMode) - [Original PR introducing this feature](https://github.com/Expensify/App/pull/42592) \ No newline at end of file