Skip to content

Calling UIManager.dispatchViewManagerCommand waits for UI changes before calling native code when building for Release on 0.64 #7543

@jaimecbernardo

Description

@jaimecbernardo

On 0.63 and when building for Debug on 0.64, when we call UIManager.dispatchViewManagerCommand the native code DispatchCommand gets called immediately. When building for Release on 0.64, DispatchCommand seems to only be called on the next UI update.

This causes some issues on modules that depend on calling DispatchCommand without doing UI updates at the same time. react-native-sketch-canvas is an example of this, since it uses PanResponder to call UIManager.dispatchViewManagerCommand to enable real time drawing.

Environment

  1. npx react-native --version:
5.0.1-alpha.2
  1. npx react-native info:
System:
    OS: Windows 10 10.0.18363
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    Memory: 7.64 GB / 15.92 GB
  Binaries:
    Node: 12.16.2 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.5 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
    npm: 6.14.4 - C:\Program Files\nodejs\npm.CMD
    Watchman: Not Found
  SDKs:
    Android SDK:
      API Levels: 23, 25, 26, 27, 28, 29
      Build Tools: 27.0.3, 28.0.3, 29.0.2, 29.0.3
      System Images: android-29 | Google APIs Intel x86 Atom, android-29 | Google APIs Intel x86 Atom_64
      Android NDK: Not Found
    Windows SDK:
      AllowDevelopmentWithoutDevLicense: Enabled
      AllowAllTrustedApps: Enabled
      Versions: 10.0.17763.0, 10.0.18362.0, 10.0.19041.0
  IDEs:
    Android Studio: Not Found
    Visual Studio: 16.9.31129.286 (Visual Studio Community 2019)
  Languages:
    Java: 1.8.0_262 - C:\Program Files\OpenJDK\openjdk-8u262-b10\bin\javac.EXE
  npmPackages:
    @react-native-community/cli: Not Found
    react: 17.0.1 => 17.0.1
    react-native: 0.64.0 => 0.64.0
    react-native-windows: ^0.64.0-0 => 0.64.3
  npmGlobalPackages:
    *react-native*: Not Found
  • Target Device(s): Desktop
  • Visual Studio Version: 2019
  • Build Configuration: Debug and Release

Steps To Reproduce

Instructions that I used to create the sample repo I pushed to: https://github.com/jaimecbernardo/reproduce-rnw64-release-dispatch-command-issue

  1. Create an app from the template:
npx react-native init ReproduceRNWReleaseBug --template react-native@^0.64.0
cd ReproduceRNWReleaseBug
npx react-native-windows-init --overwrite
  1. Add a native module that exports a command to be called by UIManager.dispatchViewManagerCommand:
winrt::Windows::UI::Xaml::FrameworkElement winrt::reproducernwreleasebug::implementation::SimpleViewManager::CreateView() noexcept
{
    auto control = winrt::Windows::UI::Xaml::Controls::TextBlock();
    control.Text(L"This text hasn't been changed yet.");
    return control;
}

winrt::Windows::Foundation::Collections::IVectorView<winrt::hstring> winrt::reproducernwreleasebug::implementation::SimpleViewManager::Commands() noexcept
{
    auto commands = winrt::single_threaded_vector<hstring>();
    commands.Append(L"changeText");
    return commands.GetView();
}

void winrt::reproducernwreleasebug::implementation::SimpleViewManager::DispatchCommand(winrt::Windows::UI::Xaml::FrameworkElement const& view, winrt::hstring const& commandId, winrt::Microsoft::ReactNative::IJSValueReader const& commandArgsReader) noexcept
{
    auto commandArgs = winrt::Microsoft::ReactNative::JSValue::ReadArrayFrom(commandArgsReader);
    if (commandId == L"changeText")
    {
        if (auto control = view.try_as<winrt::Windows::UI::Xaml::Controls::TextBlock>())
        {
            control.Text(winrt::to_hstring(commandArgs[0].AsString()));
        }
    }
}
  1. Access the command from JavaScript using UIManager.dispatchViewManagerCommand after a little delay:
          <Text>Button to change the RNSimple contents after 1 second. Works on Debug. On Release, it waits for an UI change before sending the command.</Text>
          <Button title="ChangeText" onPress={() => {
            numberOfPresses++;
            let currentPresses = numberOfPresses;
            setTimeout( () => {
              UIManager.dispatchViewManagerCommand(
                nativeCompHandle,
                UIManager.getViewManagerConfig('RNSimple').Commands.changeText,
                [ "The button has been pressed " + currentPresses + " times." ]
              );
            }, 2000);
          }} />
          <RNSimple ref={ref => {nativeCompHandle = ReactNative.findNodeHandle(ref)}} style={{flex:1}}/>
  1. Observe differences between running in Debug and Release:
npx react-native run-windows
npx react-native run-windows --release

Expected Results

I expect for DispatchCommand to be called in a timely manner in a native module's code when I call UIManager.dispatchViewManagerCommand in Release on 0.64.
Similar to how 0.63 works and how Debug on 0.64 works.

Snack, code example, screenshot, or link to a repository:

I've added a reproduction repo here: https://github.com/jaimecbernardo/reproduce-rnw64-release-dispatch-command-issue

Expected behavior on both Debug and Release after clicking the button and waiting 2 seconds:

image

When building for Release, clicking the button won't change the text after 2 seconds:

image

The text will only change after doing something that forces the UI to update, like clicking the button again.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions