Last active
October 28, 2021 18:57
-
-
Save pie6k/20beb73aaceac2bb9d02e929514da2f9 to your computer and use it in GitHub Desktop.
<Freeze /> React Component
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Goal: | |
* | |
* Being able to freeze some part of react tree and stop all updates from 'react word' for part of the tree for some period of time. | |
* It would prevent ui from updating in any way (props change, state change, hooks change etc) | |
* | |
* Use case: | |
* | |
* Let's say there is tab based react-native app. | |
* All of the screens are rendered all the time, and by using some store (redux etc) | |
* changes made in one tab might get reflected in another tab. | |
* | |
* Inactive tab might also have some inner updates (like clock components etc) | |
* | |
* We don't really want that as we dont even see inactive tab. | |
* | |
* But because of complexity, it might be hard to disable all updates easily eg. | |
* - it might be listening to relay/apollo updates | |
* - it might be listening to redux or other store | |
* - it might just have some inner timers or state that updates frequently (eg. <CountDown /> component we cannot manually stop) | |
* - etc | |
* | |
* Technically it would be possible to create some sort of context near the top of the tree like isFocusedContext, | |
* but again, it would require all different kinds of components to properly enable/disable updates using it | |
* | |
* | |
* API | |
* | |
* There would be special component called `Freeze`, and everything inside it would ignore | |
* every update in react word (both props and state/hooks based) | |
* | |
* ``` | |
* <Freeze isEnabled> | |
* <Clock /> | |
* </Freeze> | |
* ``` | |
* | |
* Even if there would be some component like `<CountDown />` inside <Freeze>, that has some inner state that is updating every second, those updates would be ignored by react and not reflected in the UI | |
* until `isEnabled` prop becomes false. | |
* | |
* Technically, those components would update their states (eg. <CountDown /> also has `ticksCount` that increases every second). | |
* This `tickCount` would increase normally, but updates would not be rendered. However, when we'd `unfreeze` it, we would see accurate state | |
* | |
* When updates are enabled again, entire tree would be re-rendered and become 'live' again | |
* | |
* | |
*/ |
const Freezer = React.memo<{ children: ReactNode; freeze: boolean }>(
({ children }) => <React.Fragment>{ children }</React.Fragment>,
(_, nextProps) => nextProps.freeze,
);
// usage
<Freezer freeze={ freeze}>
<div>
The part of the component that should not change when freeze flag is true
</div>
</Freezer>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Since this is the first Google result, lemme slap on some code here that worked for my version of this problem.
This can be partially accomplished by implementing
shouldComponentUpdate
at the desired root node of the 'freeze'. Children components that rely on the same data must retrieve it as props from the frozen parent (as opposed to react context, redux, or side-effect based data-providers).This allows control over many conditional frozen and unfrozen states.
How to implement
shouldComponentUpdate
for React hooks to disable component rerenders can be found here: https://stackoverflow.com/questions/54551949/react-hooks-how-do-i-implement-shouldcomponentupdateCaveat:
For example: The below code freeze's a component from updating so long as
criticalID
is missing from props.