Skip to content

Commit

Permalink
fix: move DelayedFreeze setImmediate into an effect (software-mansion…
Browse files Browse the repository at this point in the history
…#1980)

## Description
Executing side effects in render is usually considered bad manners in
react land, and given concurrent rendering could have unexpected results
if renders are thrown away.

## Changes
This change makes it so setImmediate fires in an effect, and also cleans
up after itself if for whatever reason the callback isn't fired.
(although I think it's probably not possible with how setImmediate is
implemented)

## Screenshots / GIFs
N/A

## Test code and steps to reproduce
We (at Discord) ran essentially this patch for probably over a year now
without issue and figured it might be good to give back.

Here's an issue related to it:
software-mansion#1198

## Checklist

- [ ] Included code example that can be used to test this change
- [ ] Updated TS types
- [ ] Updated documentation: <!-- For adding new props to native-stack
-->
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx
- [ ] Ensured that CI passes
  • Loading branch information
amadeus authored and ja1ns committed Oct 9, 2024
1 parent f2296d7 commit 1a5a790
Showing 1 changed file with 7 additions and 6 deletions.
13 changes: 7 additions & 6 deletions src/index.native.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-var-requires */
import React, { PropsWithChildren, ReactNode } from 'react';
import React, { useEffect, PropsWithChildren, ReactNode } from 'react';
import {
Animated,
Image,
Expand Down Expand Up @@ -194,13 +194,14 @@ function DelayedFreeze({ freeze, children }: FreezeWrapperProps) {
// flag used for determining whether freeze should be enabled
const [freezeState, setFreezeState] = React.useState(false);

if (freeze !== freezeState) {
// setImmediate is executed at the end of the JS execution block.
// Used here for changing the state right after the render.
setImmediate(() => {
useEffect(() => {
const id = setImmediate(() => {
setFreezeState(freeze);
});
}
return () => {
clearImmediate(id);
}
}, [freeze])

return <Freeze freeze={freeze ? freezeState : false}>{children}</Freeze>;
}
Expand Down

0 comments on commit 1a5a790

Please sign in to comment.