在自定义组件中反应原生访问 refs

Posted

技术标签:

【中文标题】在自定义组件中反应原生访问 refs【英文标题】:React native accessing refs in a custom component 【发布时间】:2016-08-11 12:04:24 【问题描述】:

我有一个自定义的 TextInput。当我编辑第一个TextInput 并点击键盘上的“下一步”时,我希望它关注第二个TextInput。我之前在 Stack Overflow 中搜索过,看来我可以使用 ref 进行搜索。但是我不确定如何使用自定义TextInput 来做到这一点。

这是我的基本 CustomTextInput 代码:

let CustomTextInput = React.createClass(
    propTypes: 
        refName: React.PropTypes.string,
        returnKeyType: React.PropTypes.string,
        onSubmitEditing: React.PropTypes.func
    ,

    getDefaultProps: function()
        return 
            refName: "",
            returnKeyType: "default",
            onSubmitEditing: () => 
        
    ,

    render: function()
        return(
            <View>
                <TextInput 
                    ref=this.props.refName
                    returnKeyType=this.props.returnKeyType
                    onSubmitEditing=this.props.onSubmitEditing
                />
            </View>
        )
    
);

module.exports = CustomTextInput

这是我的父类调用它:

let MyParent = React.createClass(
    render: function()
        return(
            <View>
                <CustomTextInput
                    refName='firstNameInput',
                    returnKeyType='next'
                    onSubmitEditing=(event) =>  
                        this.refs.lastNameInput.focus();
                    
                />
                <CustomTextInput
                    refName='lastNameInput'
                />
            </View>
        )
    
);

现在,当我按下键盘上的Next,选择firstName后,出现异常:

undefined 不是一个对象(评估 '_this2.refs.lastNameInput.focus')

我不确定我在那里做错了什么。感谢任何帮助。 :)

【问题讨论】:

【参考方案1】:

让我们从 CustomTextInput 组件开始。

export default class CustomTextInput extends Component 

componentDidMount() 
    if (this.props.onRef != null) 
        this.props.onRef(this)
    


onSubmitEditing() 
    this.props.onSubmitEditing();


focus() 
    this.textInput.focus()



render() 
    return (
        <View>
            <View style=this.state.isFocused ? styles.onFocusedStyle : styles.onBlurStyle>
                <TextInput
                    ref=input => this.textInput = input
                    onSubmitEditing=this.onSubmitEditing.bind(this)
                />
            </View>

            <Text style=styles.errorMessageField>this.state.errorStatus && this.props.errorMessage</Text>
        </View>
    );

这里我有一个示例 customTextInput。这里需要注意的重要事项是 render 方法中 TextInput 视图中的 componentDidMount()、focus() 方法和 ref 属性。

    componentDidMount() 方法将整个 CustomTextInput 组件的 ref 传递给它的父组件。通过该引用,我们将从父组件调用 CustomTextInput 组件的 focus 方法。

    这里的focus()方法通过使用CustomTextInput组件内部TextInput组件的ref将textInput聚焦在CustomTextInput组件内部。

    TextInput 的 ref 属性存储了 TextInput 的引用。该引用由 focus() 方法使用。

现在让我们看看父组件

export default class ParentComponent extends Component 
constructor(props) 
    super(props);

    this.focusNextField = this.focusNextField.bind(this);
    this.inputs = ;



focusNextField(id) 
    this.inputs[id].focus();


render() 
    return (
        <ScrollView
            contentContainerStyle=paddingBottom:100
            keyboardDismissMode='on-drag'
            scrollToTop=true>
            <View>
                    <View style=marginTop: 10>
                        <CustomTextInput
                            onRef=(ref) => 
                                this.inputs['projectName'] = ref;
                            
                            onSubmitEditing=() => 
                                this.focusNextField('projectDescription');
                            
                            />
                    </View>
                    <View style=marginTop: 10>
                        <CustomTextInput
                            onRef=(ref) => 
                                this.inputs['projectDescription'] = ref;
                            
                            onSubmitEditing=() => 
                                this.focusNextField('subDivision');
                            
                        />
                    </View>
                    <View style=marginTop: 10>
                        <CustomTextInput
                            onRef=(ref) => 
                                this.inputs['subDivision'] = ref;
                            
                            onSubmitEditing=() => 
                                this.focusNextField('plan');
                            
                           />
                    </View>

                    <View style=marginTop: 10>
                        <CustomTextInput
                            onRef=(ref) => 
                                this.inputs['plan'] = ref;
                            
                    </View>
            </View>
        </ScrollView>
    );

在父组件中,我们使用 onRef 属性存储每个 CustomTextInput 的 ref,当按下键盘的提交按钮时,我们调用下一个 CustomTextInput 的 focus 方法,CustomTextInput 的 focus 方法将 TextInput 聚焦在子组件中。

【讨论】:

非常感谢 - 我一直在努力解决这个问题,你是第一个解释清楚的人 乐于助人:) 太棒了!这对我有很大帮助!谢谢 如何在功能组件中做到这一点? @Supto @ShubhamKumar 请仔细阅读此文档,它将帮助您了解更多。如果可能的话,我会尝试更新答案。 reactjs.org/docs/refs-and-the-dom.html【参考方案2】:

这是一个对我有用的解决方案——基本上你在你的自定义组件中做了一个引用,你可以从你的父组件中的引用中访问它:

let CustomTextInput = React.createClass(
    propTypes: 
        refName: React.PropTypes.string,
        returnKeyType: React.PropTypes.string,
        onSubmitEditing: React.PropTypes.func
    ,

    getDefaultProps: function()
        return 
            refName: "",
            returnKeyType: "default",
            onSubmitEditing: () => 
        
    ,

    render: function()
        return(
            <View>
                <TextInput 
                    ref="input"
                    returnKeyType=this.props.returnKeyType
                    onSubmitEditing=this.props.onSubmitEditing
                />
            </View>
        )
    
);

module.exports = CustomTextInput

并且在父组件中:

let MyParent = React.createClass(
    render: function()
        return(
            <View>
                <CustomTextInput
                    refName='firstNameInput',
                    returnKeyType='next'
                    onSubmitEditing=(event) =>  
                        this.lastNameInput.refs.input.focus();
                    
                />
                <CustomTextInput
                    refName=ref => this.lastNameInput = ref
                />
            </View>
        )
    
);

【讨论】:

【参考方案3】:
let CustomTextInput = React.createClass(
    componentDidMount() 
        // this is to check if a refName prop is FUNCTION; 
        if (typeof this.props.rex === "function") 
            this.props.refName(this.refs.inp);
        
    

    render: function() 
        return(
            <View>
                <TextInput ref="inp"/>
            </View>
        )
    
);

let MyParent = React.createClass(
    render: function() 
        return (
            <View>
                <CustomTextInput
                    refName= (firstNameInput) => this.firstNameInput = firstNameInput 
                />
            </View>
        )
    
);

【讨论】:

【参考方案4】:

试试这个:

let AwesomeProject = React.createClass(
    onSubmitEditing:function(event)
        if (this.myTextInput !== null) 
          this.myTextInput.focus();
        
    ,
    render()
        return(
            <View>
                <CustomTextInput
                    returnKeyType='next'
                    onSubmitEditing=this.onSubmitEditing
                />
                <CustomTextInput
                    refName=(ref) => this.myTextInput = ref
                />
            </View>
        )
    
);

【讨论】:

以上是关于在自定义组件中反应原生访问 refs的主要内容,如果未能解决你的问题,请参考以下文章

使用 Swift 反应原生自定义 UI 组件:如何在事件中访问 reactTag

在自定义反应钩子中使用 axios

在自定义组件中调用 useState Hook 时反应本机 TextInput ReRenders

如何将 navigator.pop 传递给自定义反应原生组件

尝试在反应原生的自定义组件中使用两个道具,但它不起作用

在自定义组件上使用 v-for,我可以访问组件内部的 ":key" 的值吗?