2016-02-20 19 views
5

Mam ten problem, .focus() działa tylko z setTimeout, jeśli wyjmę go i przestanie działać. Czy ktoś może mi wyjaśnić, jaki jest tego powód, możliwe, że robię to niepoprawnie i jak mogę rozwiązać problem.Reagowanie ref with focus() nie działa bez setTimeout (mój przykład)

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

przykład współpracuje z setTimeout

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

JXS

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

i są na tym przykładzie React set focus on input after render

CZYNIĄ funkcyjnych

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> 
     ); 
    } 

Odpowiedz

4

Po obejrzeniu aktualizację na pytanie, zdaję sobie sprawę, że trzeba głęboko zagnieżdżony HTML przekazany do renderowanie funkcję, a element wejściowy zainteresowanie nie będzie rzeczywiście być dostępne w czasie componentDidMount rozmowy na elemencie przodka. Jak stwierdzono w React v0.13 Change Log: Aby

ref rozdzielczość zmieniła się nieznacznie, tak że sędzia do komponentu jest dostępna natychmiast po jego metoda componentDidMount nazywa; zmiana ta powinna być widoczne tylko wtedy, gdy składnik oddzwaniania danego składnika dominującego w swoim componentDidMount, który jest anty-wzorzec i należy unikać niezależnie

To twoja sprawa. Więc albo musisz rozbić strukturę HTML na osobno wyrenderowane elementy, jak opisano w here, a następnie uzyskać dostęp do elementu wejściowego we własnym wywołaniu komponentu componentDidMount; lub po prostu trzymasz się hacka odliczającego czas.

Zastosowanie componentDidMount sprawia się, że kod działa tylko wtedy, gdy składnik na którym jest nazywany jest zamontowany (patrz cytat z docs dalej w dół).

Zauważ, że wywołanie React.findDOMNodeis discouraged:

W większości przypadków, można dołączyć ref do węzła DOM i unikać findDOMNode w ogóle.

Uwaga

findDOMNode() jest luk ratunkowy umożliwia dostęp do podstawowych węzła DOM. W większości przypadków korzystanie z tego luku ewakuacyjnego jest odradzane, ponieważ przenosi abstrakcję składnika.

findDOMNode() działa tylko na zamontowanych komponentach (czyli komponentach, które zostały umieszczone w DOM).Jeśli spróbujesz wywołać to na komponencie, który nie został jeszcze podłączony (na przykład wywołanie findDOMNode() w render() na komponencie, który nie został jeszcze utworzony) zostanie zgłoszony wyjątek.

I od docs na ref string attribute:

  1. przypisać atrybut ref do niczego wrócił z render takich jak:

    <input ref="myInput" /> 
    
  2. w jakiś inny kod (zazwyczaj kod obsługi zdarzeń), dostęp do podkład instancja poprzez this.refs jak w:

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

Alternatywnie, można wyeliminować potrzebę kodu i użyć JSX autoFocus atrybut:

<ReactInputField 
     ref="titleInput" 
     autoFocus 
     ... /> 
+1

słodki odpowiedź! to jasne dla mnie – Bruce