The ref reaction with focus () does not work without setTimeout (my example)

I ran into this problem, .focus() only works with setTimeout if I select this and stop working. can someone explain to me what is the reason for this, maybe i am doing it wrong and how i can fix this problem.

  componentDidMount() { React.findDOMNode(this.refs.titleInput).getElementsByTagName('input')[0].focus(); } 

the setTimeout example works

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

Jxs

 <input ref="titleInput" type="text" /> 

and I followed this example React focus on input after rendering

rendering function

 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> ); } 
+5
source share
1 answer

After viewing the update question, I understand that you have deeply embedded HTML code passed to the rendering function, and the input element that you are interested in will not really be available when you call the DidMount component of the ancestor element. As stated in React v0.13 Change Log :

ref order of change has changed a bit, so the component reference is available immediately after calling the componentDidMount method; this change should only be seen if your component calls the parent component callback in your componentDidMount , which is an anti-pattern, and should be avoided independently

This is your case. Thus, either you must break the HTML structure into separately rendered elements, as described here , and then you will access the input element in your own callback to the DidMount component; or you just stick with the secret hack you have.

Using the DidMount component ensures that the code runs only when the component on which it is mounted is mounted (see the citation from the documentation below).

Note that calling React.findDOMNode is discouraged :

In most cases, you can attach ref to the DOM node and not use findDOMNode at all.

Note

findDOMNode() is an escape hatch used to access the base DOM node. In most cases, the use of this exit hatch is not recommended as it breaks through the abstraction of the component.

findDOMNode() only works with installed components (that is, components that were placed in the DOM). If you try to call this on a component that has not yet been installed (for example, calling findDOMNode() in render() for a component that has not yet been created), an exception is thrown.

And from the documents in the ref string attribute :

  • Assign to the ref attribute everything that was returned from render , for example:

      <input ref="myInput" /> 
  • In some other code (usually this is event handler code), refer to the support instance via this.refs , as in:

     var input = this.refs.myInput; var inputValue = input.value; var inputRect = input.getBoundingClientRect(); 

Alternatively, you can eliminate the need for code and use the JSX autoFocus attribute:

 <ReactInputField ref="titleInput" autoFocus ... /> 
+4
source

Source: https://habr.com/ru/post/1243454/


All Articles