0

I am trying to bridge an UITextField. When I try to render let React Native lay views out as it normally does, it seems to be given a height of 0. If I force the height to "100%" in the style, it works great, but my understanding is that should not be necessary.

So the question is, why is the height not working correctly without the explicit style?

Please do not try to tell me I can use an existing component. I want to understand why this doesn't work.

Demonstration: (App.tsx) Note: the TextInput included to compare to.

import React from 'react';
import {SafeAreaView, StyleSheet, Text, TextInput, View} from 'react-native';
import {NumericInput} from './NumericInput';

function App(): JSX.Element {
  return (
    <SafeAreaView>
      <View style={styles.row}>
        <Text style={styles.label}>Numeric Input</Text>
        <NumericInput style={styles.input} />
      </View>
      <View style={styles.row}>
        <Text style={styles.label}>TextInput</Text>
        <TextInput inputMode={'numeric'} style={styles.input} />
      </View>
    </SafeAreaView>
  );
}
const styles = StyleSheet.create({
  label: {flex: 2, fontSize: 24},
  input: {
    flex: 1,
    borderWidth: 1,
    fontSize: 24,
    // height: '100%',
  },
  row: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-evenly',
  },
});

export default App;

Bridging Typescript to Swift (NumericInput.tsx):

import {requireNativeComponent} from 'react-native';
import React, { HTMLAttributes, SyntheticEvent } from "react";

export interface NumericInputProps extends HTMLAttributes<SyntheticEvent>{}

export function NumericInput(props: NumericInputProps) {
  return <PGLNumericInput {...props} />;
}
const PGLNumericInput = requireNativeComponent('PGLNumericInput');

ViewManager (PGLNumericInputManager.swift)

import Foundation
import React

@available(iOS 14.0, *)
@objc(PGLNumericInputManager)
class PGLNumericInputManager: RCTViewManager, UITextFieldDelegate {
  override static func requiresMainQueueSetup() -> Bool {
    true;
  }

  override func view() -> UIView! {
    let field = PGLNumericInputField()
    field.prepareField(delegate: self)
    return field
  }
}

and actual view (PGLNumericInputView.swift)

import Foundation
import UIKit

class PGLNumericInputField : UITextField {
    func prepareField(delegate: PGLNumericInputManager) {
        self.delegate = delegate
    }
}

Note the commented-out style for height in App.tsx. Uncomment it and it works fine. A full git repo demonstrating the problem can be found here: https://github.com/dcorbin/numeric-input-height-bug

David Corbin
  • 71
  • 1
  • 6
  • probably because you don't override the default UITextField constructor anywhere, hence PGLNumericInputField() is equivalent of `let field = UITextField()`, which will have `field.frame.size` set to `(0.0, 0.0)`? I know nothing about how RN translates into Swift though, so no idea why style would help – timbre timbre May 31 '23 at 18:01
  • Per this [Stack Overflow question and answer](https://stackoverflow.com/questions/31458974/swift-do-subclasses-inherit-initializers), I think the inheritance of initializers will be automatic. Either way, width comes out fine, it's only height that doesn't work which would be very odd if your supposition is correct. Of course, current behavior is very odd. – David Corbin Jun 01 '23 at 11:36
  • Inheritance of `init` is automatic, but which `init`? the default `UITextField` init comes with (0,0) frame. So width possibly affected by other things, while height is not – timbre timbre Jun 01 '23 at 13:02
  • Manually forcing the height (set to 40) in the ViewManager had no affect. – David Corbin Jun 02 '23 at 10:50

1 Answers1

0
alignItems: 'center'

turns out to be the problem at least from one angle. If I remove that style, it will default to stretched and then RN will adjust the height to be the full height of the row. It does still feel to me like there is something the component should be doing to provide a "natural" height, but I can find no documentation that discusses it.

David Corbin
  • 71
  • 1
  • 6