disable event loop (#44169)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44169

## Changelog:
[General][Changed] Disable new event loop behavior when bridgeless (new architecture) is enabled.

# What is the problem
With event loop, specifically with `batchRenderingUpdatesInEventLoop`, prop change is not delivered to Android mounting layer if the prop change was initiated from state update inside of `useLayoutEffect`, `componentDidMount` or `componentDidUpdate`.  Note this has to be a prop change affecting mounting layer directly, not something consumed by Yoga, e.g. background colour or border colour.

This affects android only.

Minimal repro :
```
import React, {useLayoutEffect, useState} from 'react';
import {Button, SafeAreaView, View} from 'react-native';
function Foo() {
  const [bgColor, setBgColor] = React.useState('red');
  useLayoutEffect(() => {
    console.log('useLayoutEffect');
    setBgColor('blue');
  }, []);
  return (
    <View
      style={{
        backgroundColor: bgColor,
        width: '100%',
        height: '100%',
      }}
    />
  );
}
function RNTesterApp() {
  const [show, setShow] = useState(false);
  return (
    <SafeAreaView>
      <Button title="Toggle" onPress={() => setShow(!show)} />
      {show && <Foo />}
    </SafeAreaView>
  );
}
export default RNTesterApp;
```

# The underlaying problem
The problem is in batched rendering updates and how props are delivered to Android mounting layer.

Here is a step by step what happens in the repro above:
1. React issues asks Fabric to create new shadow node A with background colour **red**.
2. Fabric asks Android to allocate a view for shadow node A with background colour **red**.
3. React commits tree **T1** and calls layout effects. Meanwhile Fabric waits, without trying to mount the tree **T1**, to prevent painting state that is about to be updated and prevent flickering.
4. React clones node A, changing the background colour to **blue** and commits the new tree **T2**.
5. Fabric, will now go ahead and mount the latest tree **T2**. While creating mount instructions, it will drop prop updates because it believes prop updates where delivered already as part of step 2.

At first this might appear as a problem with view preallocation. But the underlaying trouble is that on Android, we currently have no way of knowing how to combine changesets from React into single folly::dynamic.

Reviewed By: javache, cortinico

Differential Revision: D56355863

fbshipit-source-id: f8616ee48e10fc10e129bb632c5d398842220d24
This commit is contained in:
Samuel Susla
2024-04-19 11:02:54 -07:00
committed by Facebook GitHub Bot
parent ed7766cee9
commit cf75d032d0
2 changed files with 1 additions and 21 deletions
@@ -299,21 +299,7 @@
#pragma mark - Feature Flags
class RCTAppDelegateBridgelessFeatureFlags : public facebook::react::ReactNativeFeatureFlagsDefaults {
public:
bool useModernRuntimeScheduler() override
{
return true;
}
bool enableMicrotasks() override
{
return true;
}
bool batchRenderingUpdatesInEventLoop() override
{
return true;
}
};
class RCTAppDelegateBridgelessFeatureFlags : public facebook::react::ReactNativeFeatureFlagsDefaults {};
- (void)_setUpFeatureFlags
{
@@ -49,12 +49,6 @@ public object DefaultNewArchitectureEntryPoint {
if (bridgelessEnabled) {
ReactNativeFeatureFlags.override(
object : ReactNativeFeatureFlagsDefaults() {
override fun useModernRuntimeScheduler(): Boolean = true
override fun enableMicrotasks(): Boolean = true
override fun batchRenderingUpdatesInEventLoop(): Boolean = true
override fun useNativeViewConfigsInBridgelessMode(): Boolean = fabricEnabled
})
}