Open jbcullis opened 2 years ago
setNativeProps
is pretty internal, and also going away with Fabric. What is the goal here, that cannot be accomplished using the public TextInput
API?
@NickGerleman It's a nice tool to have when building masked textboxes however I didn't realize it was on the way out so that would make sense to not implement it.
Specifically, we have a masked input control and trying to work around the nuance of rn-macos vs rn-windows. For example, rn-macos hasn't implemented casing yet so we were using toUpper as a workaround. Then we ran into the issue where cursor position was being lost when an invalid key was entered. We were able to get around these issues on mac by using a combo of defaultValue and setNativeProps however that didn't work on windows because setNativeProps doesn't seem to be implemented.
Ultimately we ended up creating a fix for the cursor position which you can find in #9615 and my intention is to make the same changes to macos tomorrow.
I've been thinking about it today and what we really need is the ability to define the data format and have the keydownpreview reject keys before it even makes it to the javascript thread...of course this needs to be considered upstream since it would apply to all platforms. Currently there is a widely acknowledge drawback to manipulating onChangeText which is you get a flicker as the characters make the round trip, preventing invalid keys at keydownpreview would solve that entirely.
Currently there is a widely acknowledge drawback to manipulating onChangeText which is you get a flicker as the characters make the round trip.
Yeah, it does seem like an inherent limitation, since any text will be entered in the control on the UI thread, before the JS thread or React is notified of the change. It seems like the manipulation would need to happen on the UI thread, as the mutation happens there. I like the idea you mentioned of adding data formats to TextInput, for it to do the masking itself. Something more immediately actionable for single use-cases would be to implement your own View Manager, that handles the TextInput logic on the native side.
For more detail on setNativeProps
, the API is mostly meant for internal components, to update the shadow node out of sync with the React component. Fabric changes a bit of how this works, so that the ShadowNode always looks like the native component properties of the React Tree. The names of native properties, etc, is implementation dependent. Guessing this is a trick that folks are using for Android/iOS right now?
@NickGerleman I hadn't used it in a while, back in the early days of react, fast typing would cause it to drop characters so we used to use it to reduce errors.
If we could set basic types like date, int, dec1, dec2, dec3, dec4, str, that would probably cover the vast majority of masked input cases for line of business apps which I suspect is the majority of rn-windows. There is also the validkeysdown prop that I've seen on a few threads in macos. I did give it a shot but it didn't restrict keys on windows.
FYI @Saadnajmi in case you have any thoughts here, re the react-native-macos
prop.
I wonder if there is a precedent in popular APIs for how these sorts of declarative "allowed text patterns" look. I do agree it is useful, and these APIs become even more useful when supported across multiple platforms.
@NickGerleman I hadn't used it in a while, back in the early days of react, fast typing would cause it to drop characters so we used to use it to reduce errors.
If we could set basic types like date, int, dec1, dec2, dec3, dec4, str, that would probably cover the vast majority of masked input cases for line of business apps which I suspect is the majority of rn-windows. There is also the validkeysdown prop that I've seen on a few threads in macos. I did give it a shot but it didn't restrict keys on windows.
ValidKeysDown is a macOS only prop. It also doesn't apply to TextInput, only View / Pressable. The closest equivalent on windows is 'keyDownEvents'. It specifies which keyboard events should only be handled in JS, and not natively. You can also specify whether to capture the event at the bubbling or capturimg phase. I'm not sure it works with textinput though.
Take a look at here for more info. https://github.com/microsoft/react-native-windows/blob/main/vnext/proposals/active/keyboard-reconcile-desktop.md#declarative-properties
In RN Tester, there is a "live rewrite" example usage of TextInput. Every space you type is replaced with underscore. And at least for macOS, a lot of the TextInput behavior didn't work till 0.66. you might want to give those a look.
Thanks @NickGerleman @Saadnajmi - unifying the api across mac and windows would be great.
I just tested onKeyDownCapture and I can see the event on windows (0.66) and can see the event but not cancel it. On mac (0.64) I cannot see the event. onKeyDownCapture={(e) => { console.log(e.nativeEvent); e.stopPropagation(); e.preventDefault(); }}
If this callback could cancel the event then we could move the masking logic here rather than onChangedText however there may be timing issues in doing this. Having the data type logic at the native thread would probably produce a more reliable result.
@jbcullis was Saad's suggestion above about looking that "live rewrite" example helpful? You're on 0.64 for macOS I take it - is upgrading to 0.66 an option?
@chrisglein i got into it a little bit yesterday, but got dragged into some support. I can see changes to the text input component on .66 but docs for macOS still list 64 as the stable version. I'll have a go at building for .66 later this week and see what happens. We are on .67 for windows. Ultimately, I think we need to prevent the round trip on masked input fields which means native support for either regex or data types are probably best suited.
I think this should be changed to a feature request since the flickering issue is prevalent on all platforms.
Hey, having access to programmatically set the TextInput
value in the UI thread would greatly benefit more customized TextInputs with a native feel! I'm having the same use case as OP.
Problem Description
Using setNativeProps({text: 'xxx'}) on a TextInput the text is not updated.
Steps To Reproduce
Create following element:
<TextInput ref={ele => this.Element = ele} defaultValue={null} onChangeText={(e) => { this.Element.setNativeProps({text: null}); }}>
Expected Results
Element should null out the field after each change.
CLI version
npx react-native --version
Environment
OS: Windows 10 10.0.22000 CPU: (16) x64 Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz Memory: 21.85 GB / 31.73 GB Binaries: Node: 16.13.0 - C:\Program Files\nodejs\node.EXE Yarn: 1.22.17 - ~\AppData\Roaming\npm\yarn.CMD npm: 8.1.3 - C:\Program Files\nodejs\npm.CMD Watchman: Not Found SDKs: Android SDK: Not Found Windows SDK: AllowDevelopmentWithoutDevLicense: Enabled AllowAllTrustedApps: Enabled Versions: 10.0.18362.0, 10.0.19041.0, 10.0.22000.0 IDEs: Android Studio: Not Found Visual Studio: 17.0.31912.275 (Visual Studio Community 2022) Languages: Java: Not Found npmPackages: @react-native-community/cli: Not Found react: 17.0.2 => 17.0.2 react-native: 0.66.0 => 0.66.0 react-native-windows: 0.66.5 => 0.66.5 npmGlobalPackages: react-native: Not Found
Target Platform Version
No response
Target Device(s)
No response
Visual Studio Version
No response
Build Configuration
No response
Snack, code example, screenshot, or link to a repository
No response