Reactjs react ref with focus()不';在没有设置超时的情况下无法工作(我的示例)

Reactjs react ref with focus()不';在没有设置超时的情况下无法工作(我的示例),reactjs,Reactjs,我遇到了这个问题,如果我取出.focus()并停止工作,它只能在setTimeout下工作。有谁能解释一下原因是什么,可能是我做得不对,如何解决这个问题 componentDidMount() { React.findDOMNode(this.refs.titleInput).getElementsByTagName('input')[0].focus(); } 使用setTimeout的示例 componentDidMount() { setTimeo

我遇到了这个问题,如果我取出
.focus()
并停止工作,它只能在
setTimeout
下工作。有谁能解释一下原因是什么,可能是我做得不对,如何解决这个问题

    componentDidMount() {
        React.findDOMNode(this.refs.titleInput).getElementsByTagName('input')[0].focus();
    }
使用setTimeout的示例

componentDidMount() {
    setTimeout(() => {
        React.findDOMNode(this.refs.titleInput).getElementsByTagName('input')[0].focus();
    }, 1);
}
JXS


我遵循了这个例子

渲染功能

render() {
        const {title, description, tagtext, siteName} = (this.state.selected !== undefined) ? this.state.selected : {};
        const hasContentChangedYet = this.hasContentChangedYet(title, description);

        return (
            <div>
                <h2 className={styles.formMainHeader}>Edit Meta-Data Form</h2>
                <table className={styles.formBlock}>
                    <tbody>
                    <tr>
                        <td className={styles.tagEditLabel}>
                            Tag
                        </td>
                        <td className={styles.inputFieldDisableContainer}>
                            {tagtext}
                        </td>
                    </tr>
                    <tr>
                        <td className={styles.tagEditLabel}>
                            Site
                        </td>
                        <td className={styles.inputFieldDisableContainer}>
                            {siteName}
                        </td>
                    </tr>
                    <tr>
                        <td className={styles.tagEditLabel}>
                            Title
                        </td>
                        <td className={styles.inputFieldContainer}>
                            <ReactInputField
                                ref="titleInput"
                                id="title"
                                defaultValue={(title) ? title : ''}
                                onChange={this.onInputChange}
                                placeholder="Title"
                                clearTool={true} />
                        </td>
                    </tr>
                    <tr>
                        <td className={styles.tagEditLabel}>
                            Description
                        </td>
                        <td className={styles.inputFieldContainer}>
                            <ReactInputField
                                id="description"
                                defaultValue={(description) ? description : ''}
                                onChange={this.onInputChange}
                                placeholder="Description"
                                clearTool={true} />
                        </td>
                    </tr>
                    </tbody>
                </table>

                <div className={styles.formFooter}>
                    <button id="save-button" className={styles.saveButton} disabled={!hasContentChangedYet} onClick={() => this.handleSavePressed()}>
                        Save
                    </button>
                    <button id="form-cancel-button" className={styles.cancelButton} onClick={this.actions.form.cancelUpdateToTagData}>
                        Cancel
                    </button>

                </div>
            </div>
        );
    }
render(){
常量{title,description,tagtext,siteName}=(this.state.selected!==未定义)?this.state.selected:{};
const hasContentChangedYet=this.hasContentChangedYet(标题、描述);
返回(
编辑元数据表单
标签
{tagtext}
场地
{siteName}
标题
描述
this.handleSavePressed()}>
拯救
取消
);
}

在看到问题的更新后,我意识到您已经将深度嵌套的HTML传递给了呈现函数,并且您感兴趣的输入元素在对祖先元素进行componentDidMount调用时确实不可用。如合同所述:

ref
解析顺序稍有更改,因此在调用组件的
componentDidMount
方法后,组件的ref立即可用;只有当组件在
componentDidMount
中调用父组件的回调时,才可以观察到此更改,这是一种反模式,无论如何都应该避免

这是你的案子。因此,或者您必须将HTML结构分解为单独呈现的元素,如前所述,然后在其自己的componentDidMount回调中访问输入元素;或者你只是坚持你的计时器

使用componentDidMount确保代码仅在其上被调用的组件装入时运行(请参阅下面文档中的引用)

请注意,调用React.findDOMNode:

在大多数情况下,您可以将ref附加到DOM节点,并完全避免使用
findDOMNode

注意

findDOMNode()
是用于访问底层DOM节点的转义图案填充。在大多数情况下,不鼓励使用此转义图案填充,因为它会穿透组件抽象

findDOMNode()
仅对已安装的组件(即已放置在DOM中的组件)起作用。如果尝试对尚未装入的组件调用此函数(如在尚未创建的组件上调用
render()
中的
findDOMNode()
),将引发异常

并从上的文档:

  • ref
    属性指定给从
    render
    返回的任何内容,例如:

     <input ref="myInput" />
    
  • 或者,您可以消除对代码的需要,并使用JSX
    autoFocus
    属性:

    <ReactInputField
            ref="titleInput"
            autoFocus
            ... />
    
    
    
    使用setTimeout()是个坏主意,而使用componentDidMount()则无关紧要。您可以在以下示例中找到问题的答案:

    在父组件中,我呈现一个包含InputText的primereact对话框:

    <Dialog visible={this.state.visible} ...>
      <InputText ref={(nameInp) => {this.nameInp = nameInp}} .../>
      ...
    </Dialog>
    
    只有在完成渲染并调用setState回调函数后,输入元素才能获得焦点

    在某些情况下,您可以简单地使用以下命令,而不是使用setState回调:

    componentDidUpdate(){
      this.nameInp.element.focus();
    }
    
    但是,每次(重新)渲染组件时都会调用componentDidUpdate(),包括在InputText隐藏的情况下

    另见:

    <Dialog visible={this.state.visible} ...>
      <InputText ref={(nameInp) => {this.nameInp = nameInp}} .../>
      ...
    </Dialog>
    
    showDlg() {
      this.setState({visible:true}, ()=>{
        this.nameInp.element.focus();
      });
    }
    
    componentDidUpdate(){
      this.nameInp.element.focus();
    }