-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Implement String ViewManager Command IDs #4667
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| placeholder='TextBox' | ||
| placeholderTextColor='rgba(225,225,225,0.7)' | ||
| editable={false} /> | ||
| <Switch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file got reformatted quite a bit since CI hasn't been enforcing our eslint file for this project. We should probably fix this, because VS Code will pick the file up and do it for you on save.
| <PropertyGroup> | ||
| <ReactNativeWindowsDir Condition="'$(ReactNativeWindowsDir)' == ''">$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\</ReactNativeWindowsDir> | ||
| </PropertyGroup> | ||
| <Import Project="$(ReactNativeWindowsDir)PropertySheets\React.Cpp.props" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't include React.cpp.props in projects external to the Microsoft.ReactNative boundary. We don't include it in the template project, and including it here actually led to it dropiing a ReactCommon folder on my C drive.
| } | ||
|
|
||
| folly::dynamic ABIViewManager::GetCommands() const { | ||
| folly::dynamic innerParent = Super::GetCommands(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our superclass always returned nothing, so removing it doesn't do anything in practice, but I don't think this should have been here to begin with.
I.e. we don't dispatch to the superclass, so even if it did has commands to report, we could never actually run them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't we fix the "dispatching to the superclass isn't working" problem then? Can you file an issue if you can't fix it in this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's fine to expect the Base View Manager won't handle anything in this case. Right now the only thing it does is assert(false) as a method to catch unhandled commands.
| const folly::dynamic &commandArgs) { | ||
| if (commandId == "setValue") { | ||
| auto value = commandArgs[0].asBool(); | ||
| viewToUpdate.as<winrt::ToggleSwitch>().IsEnabled(value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This command is kind of weird. It's iOS only upstream, and in their impl doesn't touch native props either. From what I can tell it's to fix an iOS quirk, but implementing it doesn't seem to cause us any issues, and let's us fully share iOS JS code.
|
We seem be be seeing different dumps for the internals of a switch between tests. This is possibly a timing issue. Following up with @asklar but will otherwise keep Switch out of E2ETest to unblock fixing it. |
| return commands.GetView(); | ||
| } | ||
|
|
||
| void CustomUserControlViewManagerCpp::DispatchCommand( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since we are going to support both the int and string variants for the time being, should this be an overload rather than changing it to string so we can test both cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I touched on that a little in the PR description. Internal CPP code needs to support both, but the C++ view manager exposing IDs to implementers is a departure from the C# and ObjC view managers at least.
This has some motivation to move the direction of only strings, but the bigger concern I had was around API confusion. I.e. you look at an interface and see a command id version and a string version. It's super opaque to know which to implement when.
| } | ||
|
|
||
| folly::dynamic ABIViewManager::GetCommands() const { | ||
| folly::dynamic innerParent = Super::GetCommands(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't we fix the "dispatching to the superclass isn't working" problem then? Can you file an issue if you can't fix it in this PR?
| innerParent.insert(key, value); | ||
| for (const auto &commandName : m_viewManagerWithCommands.Commands()) { | ||
| auto commandAsStr = to_string(commandName); | ||
| commandMap[commandAsStr] = commandAsStr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the Flow side, View Manager commands are untyped. Was unable to confirm whether other platforms have moved to fully using strings over the bridge yet though.
| void ViewManagerBase::TransferProperties(XamlView /*oldView*/, XamlView /*newView*/) {} | ||
|
|
||
| void ViewManagerBase::DispatchCommand( | ||
| XamlView /*viewToUpdate*/, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
XamlView [](start = 4, length = 8)
Since it is a new method, could you pass the parameter correctly by const& ?
| virtual void UpdateProperties(ShadowNodeBase *nodeToUpdate, const folly::dynamic &reactDiffMap); | ||
|
|
||
| virtual void DispatchCommand(XamlView viewToUpdate, const std::string &commandId, const folly::dynamic &commandArgs); | ||
| virtual void DispatchCommand(XamlView viewToUpdate, int64_t commandId, const folly::dynamic &commandArgs); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
XamlView viewToUpdate [](start = 31, length = 21)
XamlView is a smart pointer with additional info.
The best approach is to pass it by const& like we do for the std::string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. I'll try to bulk change everything in a followup PR instead of doing it just for this.
vmoroz
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
![]()
jonthysell
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delete the old id way internally if it's deprecated. Adding the commands for switch, we now have 3 total commands (1 in switch, 2 in scrollviewer) in the entire codebase.
| virtual void UpdateProperties(ShadowNodeBase *nodeToUpdate, const folly::dynamic &reactDiffMap); | ||
|
|
||
| virtual void DispatchCommand(XamlView viewToUpdate, const std::string &commandId, const folly::dynamic &commandArgs); | ||
| virtual void DispatchCommand(XamlView viewToUpdate, int64_t commandId, const folly::dynamic &commandArgs); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to suport the older way? There are exactly 2 existing commands in the entire core, both on scrollviewer. Update scrollviewer to the new way and completely delete the old way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I originally kept it because both still exist upstream (one marked for eventual removal), but I think you're right that we could just remove the old since we have control of our view managers and the string constant command trick.
In 0.61 Facebook added the ability to dispatch view manager commands using a string directly instead of the current indirection of getting a command ID from the view manager. This is leveraged in 0.62 in a couple places, including for Switches. UIManager overloads for string commands are added. This change impacts the C++ Microsoft.ReactNative ViewManager APIs C# and upstream view managers abstract away command IDs where they are currently left explicit in our C++ ViewManagers. Given our desire to implement built-in controls, we will need to support string commands here as well. This is made trickier with Facebook still publicly documenting grabbing command IDs from the VIewManager. Providing parallel explicit DispatchCommand functions to Microsoft.ReactNative ViewManagers would be too confusing to our users. Instead of adding parallel paths to the C++ ViewManager for commands without IDs, we remove the ID indirection entirely. Instead of internal ID mapping like we previously did with the C# ViewManagers, we now map constants to literal strings of themselves. This allows ViewManagers to accept the new form of literal string commands dispatched from JS without breaking the documented workflow of getting command IDs from the ViewManager. Eventually we should be able to remove integer only command IDs, as they are internally deprecated. Validated C# and C++ commands still work through the sample app. Validated switch behavior using the RNTester page. Fixes microsoft#4596
…ndows into stringviewmanagertemp
194d554 to
b105db4
Compare
|
@NickGerleman Please update the viewmanager docs and examples in the docs repo to reflect these changes. Since they are in 62, you should do them before the website snaps to 62. |
|
@jonthysell thanks for the heads up! I missed our existing docs for view managers when I looked before, looking again, you're totally right that they exist and document the old API. Will change today. |

In 0.61 Facebook added the ability to dispatch view manager commands using a string directly instead of the current indirection of getting a command ID from the view manager. This is leveraged in 0.62 in a couple places, including for Switches. UIManager overloads for string commands are added.
This change impacts the C++ Microsoft.ReactNative ViewManager APIs C# and upstream view managers abstract away command IDs where they are currently left explicit in our C++ ViewManagers. Given our desire to implement built-in controls, we will need to support string commands here as well. This is made trickier with Facebook still publicly documenting grabbing command IDs from the VIewManager.
Providing parallel explicit DispatchCommand functions to Microsoft.ReactNative ViewManagers would be too confusing to our users. Instead of adding parallel paths to the C++ ViewManager for commands without IDs, we remove the ID indirection entirely. Instead of internal ID mapping like we previously did with the C# ViewManagers, we now map constants to literal strings of themselves. This allows ViewManagers to accept the new form of literal string commands dispatched from JS without breaking the documented workflow of getting command IDs from the ViewManager.
Eventually we should be able to remove integer only command IDs, as they are internally deprecated.
Validated C# and C++ commands still work through the sample app. Validated switch behavior using the RNTester page.
Fixes #4596
Microsoft Reviewers: Open in CodeFlow