2016-01-17 10 views
10

Guardando in giro per vedere in che modo gli altri sviluppatori stanno gestendo l'input focus quando si lavora con Redux, ho trovato alcune linee guida generali per ReactJS components such as this. Tuttavia, la mia preoccupazione è che la funzione focus() sia imperativa e che potrei vedere strani comportamenti in cui più componenti stanno combattendo troppo a fuoco. C'è un modo redux di focalizzare l'attenzione? Qualcuno ha a che fare con pragmaticamente la messa a fuoco usando redux e reagire e se sì quali tecniche usi?Come gestire lo stato attivo utilizzando librerie dichiarative/funzionali come Redux e ReactJS?

correlati:

+3

Redux e nodi DOM/DOM funzioni, non hanno nulla a che fare con l'altro in realtà ... non sono sicuro che come vi aspettate Redux di essere coinvolti. Perché più componenti si stanno sforzando di mettere a fuoco e che tipo di strani comportamenti stai cercando di evitare? – azium

+0

Come afferma anteriormente, il redux è solo un modo per gestire e memorizzare lo stato dell'app. Quindi forse dovresti riformulare la tua domanda - stai chiedendo come gestire più componenti che hanno impostato focus() e quando vengono renderizzati su una pagina insieme vuoi decidere su quale di essi si focalizzi effettivamente? Immagino che dipenderebbe interamente dalla tua app!Di default è quello che è stato reso l'ultima volta credo. Considerare anche l'attributo 'autofocus'. –

+1

Dominic, descrivi abbastanza bene le mie preoccupazioni. Componenti multipli che intendono mettere a fuoco ma solo uno vincerà. Alla fine la visualizzazione renderizzata non sarà in sincronia con la rappresentazione dichiarativa, in parte perché con una chiamata a focus() non è più dichiarativa e anche perché l'atto di ottenere la messa a fuoco causa effetti collaterali. – jpierson

risposta

8

Il mio approccio sta usando ref callback, che è una specie di onRenderComplete di un elemento. In tale callback posso focalizzarmi (condizionatamente, se necessario) e ottenere un riferimento per la futura messa a fuoco.

Se l'input viene eseguito in modo condizionale dopo l'esecuzione di un'azione, tale callback di riferimento deve attivare un focus, poiché il riferimento non esiste ancora immediatamente dopo aver chiamato l'azione, ma solo dopo che il rendering è stato eseguito. Trattare con componentDidUpdate per cose come focus sembra solo un casino.

// Composer.jsx -- contains an input that will need to be focused somewhere else 

class Composer extends Component { 
    render() { 
    return <input type="text" ref="input" /> 
    } 

    // exposed as a public method 
    focus() { 
    this.refs.input.focus() 
    } 
} 

// App.jsx 

@connect(
    state => ({ isComposing: state.isComposing }), 
    ... 
) 
class App extends Component { 
    render() { 
    const { isComposing } = this.props // or props, doesn't matter 
    return (
     <div> 
     <button onClick={::this._onCompose}>Compose</button> 
     {isComposing ? <Composer ref={c => { 
      this._composer = c 
      this._composer && this._composer.focus() // issue initial focus 
     }} /> : null} 
     </div> 
    ) 
    } 

    _onCompose() { 
    this.props.startComposing() // fire an action that changes state.isComposing 

    // the first time the action dispatches, this._composer is still null, so the ref takes care of the focus. After the render, the ref remains so it can be accessed: 

    this._composer && this._composer.focus() // focus if ref already exists 
    } 
} 

Perché non autoFocus o isFocued prop?

Come HTMLInputElement ha value come un oggetto di scena, ma focus() come metodo - e non isFocused prop - vorrei continuare ad usare metodi per gestire questo. isFocused può ottenere un valore ma se l'utente sfuma dall'input, cosa succede a quel valore? Sarà fuori sincrono. Inoltre, come menzionato nei commenti, autoFocus può entrare in conflitto con più componenti

Quindi come decidere tra oggetti e metodi?

Per la maggior parte dei casi gli oggetti di scena saranno la risposta. I metodi possono essere utilizzati solo in un 'fire and forget', ad esempio scrollToBottom in una chat quando arriva un nuovo messaggio, scrollIntoView e così via. Si tratta di comportamenti una tantum a cui il negozio non interessa e che l'utente può modificare con un'interazione, pertanto un puntello booleano non si adatta. Per tutte le altre cose, andrei con oggetti di scena.

Ecco un jsbin:

http://jsbin.com/waholo/edit?html,js,output

Problemi correlati