You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native中能否用useRef获取元素渲染后的style属性值?

问题描述

从Xamarin转React Native的新手,希望基于通过ref引用的TextInput的borderRadius,为父View动态设置margin和padding。尝试通过inputRef.current.props.style获取样式值,但始终返回undefined,调试时发现current对象不存在props属性。

以下是自定义LabeledInput组件代码:

import React, {useState} from 'react';
import {
  View,
  Animated,
  StyleSheet,
  ViewProps,
} from 'react-native';

import {Colors} from '../../../resources/colors';
import Text from './Text';
import TextInput from './TextInput';
import {TextInputProps} from 'react-native/Libraries/Components/TextInput/TextInput';
import {isNullOrWhiteSpace} from '../../../utils/stringMethods';
import {TextProps} from 'react-native/Libraries/Text/Text';

interface LabeledInputProps {
  label: string;
  error: string;
  onChangeText: (text: string) => void;
  placeholder?: string;
  inputValue: string;
  mask?: (text: string) => string;
  validator?: (text: string) => string;
  onValidate?: (value: string) => void;
  viewProps?: ViewProps;
  textProps?: TextProps;
  errorTextProps?: TextProps;
  inputProps?: TextInputProps;
}

export default function LabeledInput(props: LabeledInputProps) {
  const inputRef = React.useRef<any>(null);
  const [dynamicStyle, setDynamicStyle] = useState(StyleSheet.create({
    dynamicContainer:{
        marginHorizonal: 0,
        paddingHorizonal: 0,
    }
  }));

  const changeTextHandler = (inputText: string) => {
    const displayText = props?.mask ? props.mask(inputText) : inputText;
    props.onChangeText(displayText);

    // ultimately not the exact behavior I'm after, but this is a simple example.
    var test = inputRef.current.props.style; 
    // props.style always returns undefined, 
    // there doesn't appear to be a 'props' property on the 'current' object when debugging.
    setDynamicStyle(StyleSheet.create({
        dynamicContainer:{
            marginHorizonal: test.borderRadius, // I want the padding/margin of this element to be
            paddingHorizonal: test.borderRadius,// dynamically set based on the inputRef's borderRadius
        }
      }))
  };

  return (
    <View
      {...props.viewProps}
      style={[
        props.viewProps?.style,
        localStyles.container,
      ]}>
      <TextInput
        ref={inputRef}
        {...props.inputProps}
        placeholder={props.placeholder}
        style={localStyles.input}
        onChangeText={changeTextHandler}
        value={props.inputValue}
      />
      <Animated.View
        pointerEvents={'none'}>
        <Text
          {...props.textProps}
          style={[props.textProps?.style, animatedStyles.label]}>
          {props.label}
        </Text>
      </Animated.View>
      {/* {stuff} */}
    </View>
  );
}

const localStyles = StyleSheet.create({
  container: {
    backgroundColor: 'blue',
    justifyContent: 'flex-start',
    flex: 1,
  },
  label: {
    fontWeight: 'bold',
    marginBottom: 8,
  },
  input: {
    padding: 8,
  },
  error: {
    backgroundColor: 'pink',
    fontSize: 12,
    paddingHorizontal: 8,
    color: Colors.danger,
    marginTop: 4,
  },
});

const animatedStyles = StyleSheet.create({
  label: {
    fontSize: 16,
    fontWeight: 'normal',
  },
});

自定义TextInput组件(已实现forwardRef):

import React, {ForwardedRef, forwardRef} from 'react';
import {TextInput as NativeTextInput, TextInputProps} from 'react-native';
import {useGlobalStyles} from '../../../resources/styles';

const TextInput = (
  props: TextInputProps,
  ref: ForwardedRef<NativeTextInput>,
) => {
  const styles = useGlobalStyles();
  return (
    <NativeTextInput
      {...props}
      ref={ref}
      style={[styles.textInput, props.style]}
      placeholderTextColor={styles.textInput.borderColor}
      onChangeText={(text: string) => {
        if (props.onChangeText) {
          props.onChangeText(text);
        }
      }}
    />
  );
};

export default forwardRef(TextInput);

解决方案

核心原因

你通过forwardRef把ref转发给了原生NativeTextInput实例,而不是React组件实例。原生组件实例没有props属性,也无法直接获取已应用的样式值(React Native没有类似Web端getComputedStyle的API),所以inputRef.current.props.style必然返回undefined。

最优实现方案:共享样式变量

最可靠且符合React理念的方式是把borderRadius提取为共享变量,让LabeledInput和TextInput共用这个值,而非通过ref读取。

步骤1:定义共享的borderRadius变量

可以在全局样式文件或组件内部定义统一的圆角值:

// 比如在resources/styles.js中
export const INPUT_BORDER_RADIUS = 8; // 根据需求调整

步骤2:在TextInput的全局样式中使用该变量

修改useGlobalStyles中的textInput样式:

import { INPUT_BORDER_RADIUS } from './constants';

export const useGlobalStyles = () => {
  return StyleSheet.create({
    textInput: {
      borderRadius: INPUT_BORDER_RADIUS,
      // 其他原有样式...
    }
  });
};

步骤3:在LabeledInput中直接使用共享变量

不再需要通过ref读取样式,直接用共享变量计算动态样式:

import { INPUT_BORDER_RADIUS } from '../../../resources/styles';

export default function LabeledInput(props: LabeledInputProps) {
  // 移除无效的inputRef样式读取逻辑
  const [dynamicStyle, setDynamicStyle] = useState({
    dynamicContainer: {
      marginHorizontal: 0,
      paddingHorizontal: 0,
    }
  });

  const changeTextHandler = (inputText: string) => {
    const displayText = props?.mask ? props.mask(inputText) : inputText;
    props.onChangeText(displayText);

    // 直接用共享变量设置动态样式
    setDynamicStyle({
      dynamicContainer: {
        marginHorizontal: INPUT_BORDER_RADIUS,
        paddingHorizontal: INPUT_BORDER_RADIUS,
      }
    });
  };

  return (
    <View
      {...props.viewProps}
      style={[
        props.viewProps?.style,
        localStyles.container,
        dynamicStyle.dynamicContainer // 应用动态样式
      ]}>
      {/* ... 其他组件代码 */}
    </View>
  );
}

可选:支持外部自定义borderRadius

如果需要允许父组件传入自定义圆角,可扩展LabeledInputProps:

interface LabeledInputProps {
  // ... 原有属性
  inputBorderRadius?: number;
}

export default function LabeledInput(props: LabeledInputProps) {
  const defaultBorderRadius = 8;
  const inputBorderRadius = props.inputBorderRadius ?? defaultBorderRadius;

  const changeTextHandler = (inputText: string) => {
    // ... 原有逻辑
    setDynamicStyle({
      dynamicContainer: {
        marginHorizontal: inputBorderRadius,
        paddingHorizontal: inputBorderRadius,
      }
    });
  };

  return (
    // ...
    <TextInput
      {...props.inputProps}
      style={[localStyles.input, { borderRadius: inputBorderRadius }]} // 传递给TextInput
      onChangeText={changeTextHandler}
      value={props.inputValue}
    />
    // ...
  );
}

内容的提问来源于stack exchange,提问作者subwizzll

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 11:31:34