diff --git a/change/react-native-windows-2020-04-22-15-02-43-stringviewmanagertemp.json b/change/react-native-windows-2020-04-22-15-02-43-stringviewmanagertemp.json
new file mode 100644
index 00000000000..9470e6bc27a
--- /dev/null
+++ b/change/react-native-windows-2020-04-22-15-02-43-stringviewmanagertemp.json
@@ -0,0 +1,8 @@
+{
+ "type": "prerelease",
+ "comment": "Implement String ViewManager Command IDs",
+ "packageName": "react-native-windows",
+ "email": "ngerlem@microsoft.com",
+ "dependentChangeType": "patch",
+ "date": "2020-04-22T22:02:43.043Z"
+}
diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleAppCPP/SampleAppCpp.vcxproj b/packages/microsoft-reactnative-sampleapps/windows/SampleAppCPP/SampleAppCpp.vcxproj
index e11f22797a5..61c4965de7d 100644
--- a/packages/microsoft-reactnative-sampleapps/windows/SampleAppCPP/SampleAppCpp.vcxproj
+++ b/packages/microsoft-reactnative-sampleapps/windows/SampleAppCPP/SampleAppCpp.vcxproj
@@ -41,7 +41,6 @@
$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\
-
Debug
diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCPP/CustomUserControlViewManagerCPP.cpp b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCPP/CustomUserControlViewManagerCPP.cpp
index 8bc8dea706e..58ce16cc054 100644
--- a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCPP/CustomUserControlViewManagerCPP.cpp
+++ b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCPP/CustomUserControlViewManagerCPP.cpp
@@ -105,18 +105,18 @@ void CustomUserControlViewManagerCpp::UpdateProperties(
}
// IViewManagerWithCommands
-IMapView CustomUserControlViewManagerCpp::Commands() noexcept {
- auto commands = winrt::single_threaded_map();
- commands.Insert(L"CustomCommand", 0);
+IVectorView CustomUserControlViewManagerCpp::Commands() noexcept {
+ auto commands = winrt::single_threaded_vector();
+ commands.Append(L"CustomCommand");
return commands.GetView();
}
void CustomUserControlViewManagerCpp::DispatchCommand(
FrameworkElement const &view,
- int64_t commandId,
+ winrt::hstring const &commandId,
IJSValueReader const &commandArgsReader) noexcept {
if (auto control = view.try_as()) {
- if (commandId == 0) {
+ if (commandId == L"CustomCommand") {
std::string arg = std::to_string(winrt::unbox_value(view.Tag()));
arg.append(", \"");
arg.append(winrt::to_string(commandArgsReader.GetString()));
diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCPP/CustomUserControlViewManagerCPP.h b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCPP/CustomUserControlViewManagerCPP.h
index 8a07bb92ac4..d9e5775e011 100644
--- a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCPP/CustomUserControlViewManagerCPP.h
+++ b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCPP/CustomUserControlViewManagerCPP.h
@@ -38,11 +38,11 @@ struct CustomUserControlViewManagerCpp
winrt::Microsoft::ReactNative::IJSValueReader const &propertyMapReader) noexcept;
// IViewManagerWithCommands
- winrt::Windows::Foundation::Collections::IMapView Commands() noexcept;
+ winrt::Windows::Foundation::Collections::IVectorView Commands() noexcept;
void DispatchCommand(
winrt::Windows::UI::Xaml::FrameworkElement const &view,
- int64_t commandId,
+ winrt::hstring const &commandId,
winrt::Microsoft::ReactNative::IJSValueReader const &commandArgsReader) noexcept;
// IViewManagerWithExportedEventTypeConstants
diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCPP/SampleLibraryCPP.vcxproj b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCPP/SampleLibraryCPP.vcxproj
index 444db48e6bc..bb3b37cbd45 100644
--- a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCPP/SampleLibraryCPP.vcxproj
+++ b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCPP/SampleLibraryCPP.vcxproj
@@ -17,7 +17,6 @@
10.0.16299.0
-
Debug
diff --git a/vnext/Desktop.DLL/react-native-win32.x64.def b/vnext/Desktop.DLL/react-native-win32.x64.def
index 280de54d461..253bc9d1dfa 100644
--- a/vnext/Desktop.DLL/react-native-win32.x64.def
+++ b/vnext/Desktop.DLL/react-native-win32.x64.def
@@ -34,7 +34,7 @@ EXPORTS
?createIUIManager@react@facebook@@YA?AV?$shared_ptr@VIUIManager@react@facebook@@@std@@$$QEAV?$vector@V?$unique_ptr@VIViewManager@react@facebook@@U?$default_delete@VIViewManager@react@facebook@@@std@@@std@@V?$allocator@V?$unique_ptr@VIViewManager@react@facebook@@U?$default_delete@VIViewManager@react@facebook@@@std@@@std@@@2@@4@PEAUINativeUIManager@12@@Z
?createUIManagerModule@react@facebook@@YA?AV?$unique_ptr@VCxxModule@module@xplat@facebook@@U?$default_delete@VCxxModule@module@xplat@facebook@@@std@@@std@@V?$shared_ptr@VIUIManager@react@facebook@@@4@@Z
?destroy@dynamic@folly@@AEAAXXZ
-?dispatchCommand@ShadowNode@react@facebook@@UEAAX_JAEBUdynamic@folly@@@Z
+?dispatchCommand@ShadowNode@react@facebook@@UEAAXAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBUdynamic@folly@@@Z
?getModuleRegistry@Instance@react@facebook@@QEAAAEAVModuleRegistry@23@XZ
?get_ptr@dynamic@folly@@QEGBAPEBU12@V?$Range@PEBD@2@@Z
?get_ptrImpl@dynamic@folly@@AEGBAPEBU12@AEBU12@@Z
diff --git a/vnext/Desktop.DLL/react-native-win32.x86.def b/vnext/Desktop.DLL/react-native-win32.x86.def
index 9ae703e4de2..8a299514bc9 100644
--- a/vnext/Desktop.DLL/react-native-win32.x86.def
+++ b/vnext/Desktop.DLL/react-native-win32.x86.def
@@ -35,7 +35,7 @@ EXPORTS
?createIUIManager@react@facebook@@YG?AV?$shared_ptr@VIUIManager@react@facebook@@@std@@$$QAV?$vector@V?$unique_ptr@VIViewManager@react@facebook@@U?$default_delete@VIViewManager@react@facebook@@@std@@@std@@V?$allocator@V?$unique_ptr@VIViewManager@react@facebook@@U?$default_delete@VIViewManager@react@facebook@@@std@@@std@@@2@@4@PAUINativeUIManager@12@@Z
?createUIManagerModule@react@facebook@@YG?AV?$unique_ptr@VCxxModule@module@xplat@facebook@@U?$default_delete@VCxxModule@module@xplat@facebook@@@std@@@std@@V?$shared_ptr@VIUIManager@react@facebook@@@4@@Z
?destroy@dynamic@folly@@AAEXXZ
-?dispatchCommand@ShadowNode@react@facebook@@UAEX_JABUdynamic@folly@@@Z
+?dispatchCommand@ShadowNode@react@facebook@@UAEXABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABUdynamic@folly@@@Z
?getModuleRegistry@Instance@react@facebook@@QAEAAVModuleRegistry@23@XZ
?get_ptr@dynamic@folly@@QGBEPBU12@V?$Range@PBD@2@@Z
?get_ptrImpl@dynamic@folly@@AGBEPBU12@ABU12@@Z
diff --git a/vnext/Desktop.UnitTests/EmptyUIManagerModule.h b/vnext/Desktop.UnitTests/EmptyUIManagerModule.h
index 6006bb2ca44..f8e333ea0bb 100644
--- a/vnext/Desktop.UnitTests/EmptyUIManagerModule.h
+++ b/vnext/Desktop.UnitTests/EmptyUIManagerModule.h
@@ -63,7 +63,10 @@ class EmptyUIManager {
std::function /*final Callback*/ callback);
void setJSResponder(int64_t reactTag, bool blockNativeResponder);
void clearJSResponder();
- void dispatchViewManagerCommand(int64_t reactTag, int64_t commandId, folly::dynamic /*ReadableMap*/ commandArgs);
+ void dispatchViewManagerCommand(
+ int64_t reactTag,
+ const std::string &commandId,
+ folly::dynamic /*ReadableMap*/ commandArgs);
void showPopupMenu(
int64_t reactTag,
folly::dynamic /*ReadableMap*/ items,
diff --git a/vnext/Microsoft.ReactNative.SharedManaged/AttributedViewManager.cs b/vnext/Microsoft.ReactNative.SharedManaged/AttributedViewManager.cs
index b590c2bfb96..56691b2be2f 100644
--- a/vnext/Microsoft.ReactNative.SharedManaged/AttributedViewManager.cs
+++ b/vnext/Microsoft.ReactNative.SharedManaged/AttributedViewManager.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Windows.UI.Xaml;
@@ -192,27 +193,21 @@ private static bool IsEnum(Type t)
#region Commands
- public virtual IReadOnlyDictionary Commands
+ public virtual IReadOnlyList Commands
{
get
{
if (null == _commands)
{
- var commands = new Dictionary();
+ _commands = ViewManagerCommands.Keys.ToList();
- foreach (var kvp in ViewManagerCommands)
- {
- commands.Add(kvp.Value.CommandName, kvp.Value.CommandId);
- }
-
- _commands = commands;
}
return _commands;
}
}
- private IReadOnlyDictionary _commands;
+ private IReadOnlyList _commands;
- public virtual void DispatchCommand(FrameworkElement view, long commandId, IJSValueReader commandArgsReader)
+ public virtual void DispatchCommand(FrameworkElement view, string commandId, IJSValueReader commandArgsReader)
{
if (view is TFrameworkElement viewAsT)
{
@@ -227,13 +222,13 @@ public virtual void DispatchCommand(FrameworkElement view, long commandId, IJSVa
}
}
- internal Dictionary> ViewManagerCommands
+ internal Dictionary> ViewManagerCommands
{
get
{
if (null == _viewManagerCommands)
{
- var viewManagerCommands = new Dictionary>();
+ var viewManagerCommands = new Dictionary>();
foreach (var methodInfo in GetType().GetTypeInfo().DeclaredMethods)
{
@@ -243,10 +238,9 @@ internal Dictionary> ViewManagerComm
var command = new ViewManagerCommand
{
CommandName = commandAttribute.CommandName ?? methodInfo.Name,
- CommandId = viewManagerCommands.Count,
CommandMethod = MakeReaderMethod(methodInfo)
};
- viewManagerCommands.Add(command.CommandId, command);
+ viewManagerCommands.Add(command.CommandName, command);
}
}
@@ -255,12 +249,11 @@ internal Dictionary> ViewManagerComm
return _viewManagerCommands;
}
}
- private Dictionary> _viewManagerCommands;
+ private Dictionary> _viewManagerCommands;
internal struct ViewManagerCommand where U : TFrameworkElement
{
public string CommandName;
- public long CommandId;
public Action CommandMethod;
}
diff --git a/vnext/Microsoft.ReactNative/ABIViewManager.cpp b/vnext/Microsoft.ReactNative/ABIViewManager.cpp
index 0fd72679c1c..fc85aff39d0 100644
--- a/vnext/Microsoft.ReactNative/ABIViewManager.cpp
+++ b/vnext/Microsoft.ReactNative/ABIViewManager.cpp
@@ -115,29 +115,31 @@ void ABIViewManager::UpdateProperties(react::uwp::ShadowNodeBase *nodeToUpdate,
}
folly::dynamic ABIViewManager::GetCommands() const {
- folly::dynamic innerParent = Super::GetCommands();
+ folly::dynamic commandMap = folly::dynamic::object();
+ // Why are we providing commands with the same key and value? React Native 0.61 internally introduced string command
+ // IDs which can be dispatched directly without querying the ViewManager for commands. Integer command IDs are
+ // internally deprecated, but querying for command ID is still the documented path. Returning constants as their
+ // string lets us internally only support the string path.
if (m_viewManagerWithCommands) {
- auto outerChild = m_viewManagerWithCommands.Commands();
- for (const auto &pair : outerChild) {
- std::string key = to_string(pair.Key());
- folly::dynamic value{pair.Value()};
- innerParent.insert(key, value);
+ for (const auto &commandName : m_viewManagerWithCommands.Commands()) {
+ auto commandAsStr = to_string(commandName);
+ commandMap[commandAsStr] = commandAsStr;
}
}
- return innerParent;
+ return commandMap;
}
void ABIViewManager::DispatchCommand(
winrt::Windows::UI::Xaml::DependencyObject viewToUpdate,
- int64_t commandId,
+ const std::string &commandId,
const folly::dynamic &commandArgs) {
if (m_viewManagerWithCommands) {
auto view = viewToUpdate.as();
IJSValueReader argReader = winrt::make(commandArgs);
- m_viewManagerWithCommands.DispatchCommand(view, commandId, argReader);
+ m_viewManagerWithCommands.DispatchCommand(view, to_hstring(commandId), argReader);
}
}
diff --git a/vnext/Microsoft.ReactNative/ABIViewManager.h b/vnext/Microsoft.ReactNative/ABIViewManager.h
index 4356f6dabeb..3b2e55ae57a 100644
--- a/vnext/Microsoft.ReactNative/ABIViewManager.h
+++ b/vnext/Microsoft.ReactNative/ABIViewManager.h
@@ -40,7 +40,7 @@ class ABIViewManager : public react::uwp::FrameworkElementViewManager {
void DispatchCommand(
winrt::Windows::UI::Xaml::DependencyObject viewToUpdate,
- int64_t commandId,
+ const std::string &commandId,
const folly::dynamic &commandArgs) override;
folly::dynamic GetExportedCustomBubblingEventTypeConstants() const override;
diff --git a/vnext/Microsoft.ReactNative/IViewManager.idl b/vnext/Microsoft.ReactNative/IViewManager.idl
index 68598f48659..226bcf9703d 100644
--- a/vnext/Microsoft.ReactNative/IViewManager.idl
+++ b/vnext/Microsoft.ReactNative/IViewManager.idl
@@ -40,7 +40,7 @@ namespace Microsoft.ReactNative
[webhosthidden]
interface IViewManagerWithNativeProperties
{
- Windows.Foundation.Collections.IMapView NativeProps { get; };
+ IMapView NativeProps { get; };
void UpdateProperties(Windows.UI.Xaml.FrameworkElement view, IJSValueReader propertyMapReader);
}
@@ -48,9 +48,9 @@ namespace Microsoft.ReactNative
[webhosthidden]
interface IViewManagerWithCommands
{
- Windows.Foundation.Collections.IMapView Commands { get; };
+ IVectorView Commands { get; };
- void DispatchCommand(Windows.UI.Xaml.FrameworkElement view, Int64 commandId, IJSValueReader commandArgsReader);
+ void DispatchCommand(Windows.UI.Xaml.FrameworkElement view, String commandId, IJSValueReader commandArgsReader);
}
[webhosthidden]
diff --git a/vnext/ReactUWP/Views/ScrollViewManager.cpp b/vnext/ReactUWP/Views/ScrollViewManager.cpp
index 8e3a021ab84..bbe699e9e4b 100644
--- a/vnext/ReactUWP/Views/ScrollViewManager.cpp
+++ b/vnext/ReactUWP/Views/ScrollViewManager.cpp
@@ -11,10 +11,10 @@
namespace react {
namespace uwp {
-enum class ScrollViewCommands {
- ScrollTo = 1,
- ScrollToEnd,
-};
+namespace ScrollViewCommands {
+constexpr const char *ScrollTo = "scrollTo";
+constexpr const char *ScrollToEnd = "scrollToEnd";
+}; // namespace ScrollViewCommands
class ScrollViewShadowNode : public ShadowNodeBase {
using Super = ShadowNodeBase;
@@ -22,7 +22,7 @@ class ScrollViewShadowNode : public ShadowNodeBase {
public:
ScrollViewShadowNode();
~ScrollViewShadowNode();
- void dispatchCommand(int64_t commandId, const folly::dynamic &commandArgs) override;
+ void dispatchCommand(const std::string &commandId, const folly::dynamic &commandArgs) override;
void createView() override;
void updateProperties(const folly::dynamic &&props) override;
@@ -65,28 +65,23 @@ ScrollViewShadowNode::~ScrollViewShadowNode() {
m_SIPEventHandler.reset();
}
-void ScrollViewShadowNode::dispatchCommand(int64_t commandId, const folly::dynamic &commandArgs) {
+void ScrollViewShadowNode::dispatchCommand(const std::string &commandId, const folly::dynamic &commandArgs) {
const auto scrollViewer = GetView().as();
if (scrollViewer == nullptr)
return;
- switch (commandId) {
- case static_cast(ScrollViewCommands::ScrollTo): {
- double x = commandArgs[0].asDouble();
- double y = commandArgs[1].asDouble();
- bool animated = commandArgs[2].asBool();
- scrollViewer.ChangeView(x, y, nullptr, !animated /*disableAnimation*/);
- break;
- }
- case static_cast(ScrollViewCommands::ScrollToEnd): {
- bool animated = commandArgs[0].asBool();
- bool horiz = scrollViewer.HorizontalScrollMode() == winrt::ScrollMode::Auto;
- if (horiz)
- scrollViewer.ChangeView(scrollViewer.ScrollableWidth(), nullptr, nullptr, !animated /*disableAnimation*/);
- else
- scrollViewer.ChangeView(nullptr, scrollViewer.ScrollableHeight(), nullptr, !animated /*disableAnimation*/);
- break;
- }
+ if (commandId == ScrollViewCommands::ScrollTo) {
+ double x = commandArgs[0].asDouble();
+ double y = commandArgs[1].asDouble();
+ bool animated = commandArgs[2].asBool();
+ scrollViewer.ChangeView(x, y, nullptr, !animated /*disableAnimation*/);
+ } else if (commandId == ScrollViewCommands::ScrollToEnd) {
+ bool animated = commandArgs[0].asBool();
+ bool horiz = scrollViewer.HorizontalScrollMode() == winrt::ScrollMode::Auto;
+ if (horiz)
+ scrollViewer.ChangeView(scrollViewer.ScrollableWidth(), nullptr, nullptr, !animated /*disableAnimation*/);
+ else
+ scrollViewer.ChangeView(nullptr, scrollViewer.ScrollableHeight(), nullptr, !animated /*disableAnimation*/);
}
}
@@ -413,11 +408,10 @@ const char *ScrollViewManager::GetName() const {
}
folly::dynamic ScrollViewManager::GetCommands() const {
- auto commands = Super::GetCommands();
- commands.update(folly::dynamic::object(
- "scrollTo", static_cast>(ScrollViewCommands::ScrollTo))(
- "scrollToEnd", static_cast>(ScrollViewCommands::ScrollToEnd)));
- return commands;
+ // Upstream JS will dispatch the string directly instead of ever actually calling this, but providing a real
+ // implementation is simple enough in case anything changes.
+ return folly::dynamic::object(ScrollViewCommands::ScrollTo, ScrollViewCommands::ScrollTo)(
+ ScrollViewCommands::ScrollToEnd, ScrollViewCommands::ScrollToEnd);
}
folly::dynamic ScrollViewManager::GetNativeProps() const {
diff --git a/vnext/ReactUWP/Views/ShadowNodeBase.cpp b/vnext/ReactUWP/Views/ShadowNodeBase.cpp
index c03d97ed666..527c30e5a88 100644
--- a/vnext/ReactUWP/Views/ShadowNodeBase.cpp
+++ b/vnext/ReactUWP/Views/ShadowNodeBase.cpp
@@ -44,7 +44,7 @@ bool ShadowNodeBase::NeedsForceLayout() {
return false;
}
-void ShadowNodeBase::dispatchCommand(int64_t commandId, const folly::dynamic &commandArgs) {
+void ShadowNodeBase::dispatchCommand(const std::string &commandId, const folly::dynamic &commandArgs) {
GetViewManager()->DispatchCommand(GetView(), commandId, commandArgs);
}
diff --git a/vnext/ReactUWP/Views/SwitchViewManager.cpp b/vnext/ReactUWP/Views/SwitchViewManager.cpp
index e5ad8a0c5a5..93093cdf36e 100644
--- a/vnext/ReactUWP/Views/SwitchViewManager.cpp
+++ b/vnext/ReactUWP/Views/SwitchViewManager.cpp
@@ -160,5 +160,17 @@ bool SwitchViewManager::UpdateProperty(
return true;
}
+void SwitchViewManager::DispatchCommand(
+ XamlView viewToUpdate,
+ const std::string &commandId,
+ const folly::dynamic &commandArgs) {
+ if (commandId == "setValue") {
+ auto value = commandArgs[0].asBool();
+ viewToUpdate.as().IsEnabled(value);
+ } else {
+ Super::DispatchCommand(viewToUpdate, commandId, commandArgs);
+ }
+}
+
} // namespace uwp
} // namespace react
diff --git a/vnext/ReactUWP/Views/SwitchViewManager.h b/vnext/ReactUWP/Views/SwitchViewManager.h
index aaa6089c809..372163eb095 100644
--- a/vnext/ReactUWP/Views/SwitchViewManager.h
+++ b/vnext/ReactUWP/Views/SwitchViewManager.h
@@ -17,6 +17,7 @@ class SwitchViewManager : public ControlViewManager {
const char *GetName() const override;
folly::dynamic GetNativeProps() const override;
facebook::react::ShadowNode *createShadow() const override;
+ void DispatchCommand(XamlView viewToUpdate, const std::string &commandId, const folly::dynamic &commandArgs) override;
protected:
bool UpdateProperty(
diff --git a/vnext/ReactUWP/Views/ViewManagerBase.cpp b/vnext/ReactUWP/Views/ViewManagerBase.cpp
index 38feb176955..86d1e61e084 100644
--- a/vnext/ReactUWP/Views/ViewManagerBase.cpp
+++ b/vnext/ReactUWP/Views/ViewManagerBase.cpp
@@ -255,7 +255,7 @@ void ViewManagerBase::TransferProperties(XamlView /*oldView*/, XamlView /*newVie
void ViewManagerBase::DispatchCommand(
XamlView /*viewToUpdate*/,
- int64_t /*commandId*/,
+ const std::string & /*commandId*/,
const folly::dynamic & /*commandArgs*/) {
assert(false); // View did not handle its command
}
diff --git a/vnext/ReactWindowsCore/IUIManager.h b/vnext/ReactWindowsCore/IUIManager.h
index 4cf28835a16..cb677aa75aa 100644
--- a/vnext/ReactWindowsCore/IUIManager.h
+++ b/vnext/ReactWindowsCore/IUIManager.h
@@ -44,7 +44,8 @@ class IUIManager {
folly::dynamic &addChildTags,
folly::dynamic &addAtIndices,
folly::dynamic &removeFrom) = 0;
- virtual void dispatchViewManagerCommand(int64_t reactTag, int64_t commandId, folly::dynamic &&commandArgs) = 0;
+ virtual void
+ dispatchViewManagerCommand(int64_t reactTag, const std::string &commandId, folly::dynamic &&commandArgs) = 0;
virtual void replaceExistingNonRootView(int64_t oldTag, int64_t newTag) = 0;
virtual void measure(int64_t reactTag, facebook::xplat::module::CxxModule::Callback callback) = 0;
virtual void measureInWindow(int64_t reactTag, facebook::xplat::module::CxxModule::Callback callback) = 0;
diff --git a/vnext/ReactWindowsCore/Modules/UIManagerModule.cpp b/vnext/ReactWindowsCore/Modules/UIManagerModule.cpp
index b71f31bd556..7d72ac8d25a 100644
--- a/vnext/ReactWindowsCore/Modules/UIManagerModule.cpp
+++ b/vnext/ReactWindowsCore/Modules/UIManagerModule.cpp
@@ -320,7 +320,10 @@ void UIManager::replaceExistingNonRootView(int64_t oldTag, int64_t newTag) {
manageChildren(parent.m_tag, emptyVec, emptyVec, tagToAdd, indicesToAdd, indicesToRemove);
}
-void UIManager::dispatchViewManagerCommand(int64_t reactTag, int64_t commandId, folly::dynamic &&commandArgs) {
+void UIManager::dispatchViewManagerCommand(
+ int64_t reactTag,
+ const std::string &commandId,
+ folly::dynamic &&commandArgs) {
m_nativeUIManager->ensureInBatch();
auto &node = m_nodeRegistry.getNode(reactTag);
if (!node.m_zombie)
@@ -507,8 +510,11 @@ std::vector UIManagerModule::getMeth
Method(
"dispatchViewManagerCommand",
[manager](dynamic args) {
+ // 0.61 allows directly dispatching command names instead of querying the ViewManager for the command ID.
+ // In stock React Native, integer commands are deprecated but not yet removed. RNW APIs only allow strings,
+ // and provide command constants as their literal string.
manager->dispatchViewManagerCommand(
- jsArgAsInt(args, 0), jsArgAsInt(args, 1), std::move(jsArgAsDynamic(args, 2)));
+ jsArgAsInt(args, 0), jsArgAsString(args, 1), std::move(jsArgAsDynamic(args, 2)));
}),
Method("measure", [manager](dynamic args, Callback cb) { manager->measure(jsArgAsInt(args, 0), cb); }),
Method(
diff --git a/vnext/ReactWindowsCore/Modules/UIManagerModule.h b/vnext/ReactWindowsCore/Modules/UIManagerModule.h
index cf79bb89346..e66f5d5e9ac 100644
--- a/vnext/ReactWindowsCore/Modules/UIManagerModule.h
+++ b/vnext/ReactWindowsCore/Modules/UIManagerModule.h
@@ -43,7 +43,9 @@ class UIManager : public IUIManager, INativeUIManagerHost {
folly::dynamic &addChildTags,
folly::dynamic &addAtIndices,
folly::dynamic &removeFrom) override;
- void dispatchViewManagerCommand(int64_t reactTag, int64_t commandId, folly::dynamic &&commandArgs) override;
+
+ void dispatchViewManagerCommand(int64_t reactTag, const std::string &commandId, folly::dynamic &&commandArgs)
+ override;
void replaceExistingNonRootView(int64_t oldTag, int64_t newTag) override;
void onBatchComplete() override;
void measure(int64_t reactTag, facebook::xplat::module::CxxModule::Callback callback) override;
diff --git a/vnext/ReactWindowsCore/ShadowNode.cpp b/vnext/ReactWindowsCore/ShadowNode.cpp
index 6bf17eb9261..626015b0423 100644
--- a/vnext/ReactWindowsCore/ShadowNode.cpp
+++ b/vnext/ReactWindowsCore/ShadowNode.cpp
@@ -8,7 +8,7 @@ namespace react {
ShadowNode::~ShadowNode() {}
-void ShadowNode::dispatchCommand(int64_t commandId, const folly::dynamic &commandArgs) {}
+void ShadowNode::dispatchCommand(const std::string &commandId, const folly::dynamic &commandArgs) {}
void ShadowNode::onDropViewInstance() {}
diff --git a/vnext/ReactWindowsCore/ShadowNode.h b/vnext/ReactWindowsCore/ShadowNode.h
index 4f986e2f108..ea10f0259db 100644
--- a/vnext/ReactWindowsCore/ShadowNode.h
+++ b/vnext/ReactWindowsCore/ShadowNode.h
@@ -20,7 +20,7 @@ struct ShadowNode {
virtual void updateProperties(const folly::dynamic &&props);
virtual void onDropViewInstance() = 0;
- virtual void dispatchCommand(int64_t commandId, const folly::dynamic &commandArgs);
+ virtual void dispatchCommand(const std::string &commandId, const folly::dynamic &commandArgs);
virtual void removeAllChildren() = 0;
virtual void AddView(ShadowNode &child, int64_t index) = 0;
virtual void RemoveChildAt(int64_t indexToRemove) = 0;
diff --git a/vnext/include/ReactUWP/Views/ShadowNodeBase.h b/vnext/include/ReactUWP/Views/ShadowNodeBase.h
index e8ec8da550f..2e008780943 100644
--- a/vnext/include/ReactUWP/Views/ShadowNodeBase.h
+++ b/vnext/include/ReactUWP/Views/ShadowNodeBase.h
@@ -54,7 +54,7 @@ struct REACTWINDOWS_EXPORT ShadowNodeBase : public facebook::react::ShadowNode {
virtual ~ShadowNodeBase() {}
virtual void onDropViewInstance() override;
- virtual void dispatchCommand(int64_t commandId, const folly::dynamic &commandArgs) override;
+ virtual void dispatchCommand(const std::string &commandId, const folly::dynamic &commandArgs) override;
virtual void removeAllChildren() override;
virtual void AddView(ShadowNode &child, int64_t index) override;
virtual void RemoveChildAt(int64_t indexToRemove) override;
diff --git a/vnext/include/ReactUWP/Views/ViewManagerBase.h b/vnext/include/ReactUWP/Views/ViewManagerBase.h
index 17f2e2ae6c0..b1ff720d35a 100644
--- a/vnext/include/ReactUWP/Views/ViewManagerBase.h
+++ b/vnext/include/ReactUWP/Views/ViewManagerBase.h
@@ -62,7 +62,7 @@ class REACTWINDOWS_EXPORT ViewManagerBase : public facebook::react::IViewManager
virtual void UpdateProperties(ShadowNodeBase *nodeToUpdate, const folly::dynamic &reactDiffMap);
- virtual void DispatchCommand(XamlView viewToUpdate, int64_t commandId, const folly::dynamic &commandArgs);
+ virtual void DispatchCommand(XamlView viewToUpdate, const std::string &commandId, const folly::dynamic &commandArgs);
// Yoga Layout
virtual void