2017-10-30 4 views
2

Also verwende ich einen Hash, um die Werte der dynamisch erstellten Reihen von Eingabewerten zu speichern, und ich verliere den Fokus auf die Eingabe, die ich nach Eingabe nur eines Zeichens modifiziere. Ich denke, die Lösung dafür könnte sein, Refs zu verwenden, um sich nur auf die zuletzt geänderte Eingabe zu konzentrieren, aber ich konnte es nicht zum Laufen bringen, da ich nicht herausfinden konnte, welches Element zuletzt geändert wurde. Ratschläge, wie dies zu lösen ist, werden geschätzt.reactjs Eingabeelement verliert Fokus nach Tastendruck

Der folgende Code erstellt dynamisch Eingabefelder und sucht ihre Werte basierend auf dem UnitPriceValueHash. Jede Variante hat eine ID, und ID wird als Schlüssel für den Hash verwendet.

Ich habe einen Codepen erstellt, um zu versuchen und das Problem neu zu erstellen, aber das Problem im Gesicht zeigt sich nicht in Code-Stift. In meiner aktuellen App drücke ich zB 1 in das Eingabefeld, dann steht der Cursor nicht mehr auf dem Eingabefeld.

https://codepen.io/ByteSize/pen/oogLpE?editors=1011

Der einzige Unterschied zwischen dem codepen und meinem Code erscheint in einer Tabelle die Tatsache, die die Eingänge verschachtelt zu sein.

Inputs nested in table

CreateItem(variant) { 
    const unitPriceValueHash = this.props.unitPriceValueHash 
    return { 
     variant_title: variant.variant_title, 
     variant_price: variant.variant_price, 
     unit_cost: <TextField 
        type="number" 
        onChange={(event) => this.handleUnitPriceChange(variant.id, event)} 
        key={variant.id} 
        value={unitPriceValueHash[variant.id] || ''} 
       /> 
    }; 
    } 

Unten ist die Zustandsänderung, die den Hash-

handleUnitPriceChange (id, event) { 
    const unitPriceValueHash = this.state.unitPriceValueHash 
    unitPriceValueHash[id] = event 
    console.log(unitPriceValueHash) 
    this.setState({unitPriceValueHash: unitPriceValueHash}); 
    //this.updateVariantUnitCost(id, event); 
    } 

Antwort

0

Die Lösung für dieses Problem hatte ich einen Zwischenzustand, um den Wert des Eingabefeldes auf Änderung zu speichern, und eine AJAX-Anforderung auf einem

onBlur einreichen
class TextFieldWrapper extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     value: this.props.variantValue[this.props.variantId] || '', 
    } 
    this.handleUnitPriceChange = this.handleUnitPriceChange.bind(this) 
    this.updateValue = this.updateValue.bind(this) 
    } 
    updateValue(value){ 
    this.setState({ 
     value: value, 
    }); 
    } 
    handleUnitPriceChange() { 
    this.props.onUnitPriceChange(this.props.variantId, this.state.value); 
    } 
    render(){ 
    return (
     <TextField 
     type="number" 
     id={this.props.variantId} 
     key={this.props.variantId} 
     onChange={this.updateValue} 
     onBlur={this.handleUnitPriceChange} 
     value={this.state.value} 
     /> 
    ); 
    } 
} 
+1

Verwenden Sie nicht '.bind (this)' inline in den Requisiten - es leidet unter dem gleichen Problem, das ich in meiner Antwort erwähnte (es erstellt eine neue Funktion bei jedem Render). Besser, das im Konstruktor zu tun. – caesay

1

Es gibt ein paar Probleme mit dem Code verändert haben Ihnen geteilt.

  • Verwenden Sie keine Inline-Funktionen. Jedes Rendering, die Funktion wird erneut erstellt, was bedeutet, dass wenn die Requisiten verglichen werden, es so aussieht, als ob die Funktion anders ist (es ist jedes Mal eine neue/andere Funktion!) Und reagiert dann erneut.
  • Ändern Sie keine Objekte, die in diesem Zustand vorhanden sind, sondern erstellen Sie ein neues Objekt. Wenn Sie ein Objekt ändern, das in diesem Status vorhanden ist, möchten Sie im Wesentlichen angeben, dass Render nicht konsistent und reproduzierbar sein sollen.

Ich habe neu geschrieben ursprünglichen Code mit den Themen

hervorgehoben
CreateItem(variant) { 
    const unitPriceValueHash = this.props.unitPriceValueHash 
    return { 
    variant_title: variant.variant_title, 
    variant_price: variant.variant_price, 
    unit_cost: <TextField 
     type="number" 
     onChange={(event) => this.handleUnitPriceChange(variant.id, event)} 
     // ^^^^ - inline functions cause react to re-render every time, instead - create a component 
     key={variant.id} 
     value={unitPriceValueHash[variant.id] || ''} 
    /> 
    }; 
} 

handleUnitPriceChange(id, event) { 
    const unitPriceValueHash = this.state.unitPriceValueHash 
    unitPriceValueHash[id] = event 
    // ^^^^ - please, please - don't do this. You can't mutate the state like this. 

    // instead, do the following to create a new modified object without modifying the object in the state 
    const unitPriceValueHash = Object.assign({}, this.state.unitPriceValueHash, { id: event }); 
    this.setState({ unitPriceValueHash: unitPriceValueHash }); 
} 

In Bezug auf die Inline-Funktion, in der Regel die Empfehlung ist eine neue Komponente für diese zu schaffen, die den Wert nimmt eine Stütze. Das könnte wie folgt aussehen:

class UnitCost extends PureComponent { 
    static propTypes = { 
    variantId: PropTypes.number, 
    variantValue: PropTypes.object, 
    onUnitPriceChange: PropTypes.func, 
    } 
    handleUnitPriceChange(e) { 
    this.props.onUnitPriceChange(this.props.variantId, e) 
    } 
    render() { 
    return (
     <TextField 
     type="number" 
     onChange={this.handleUnitPriceChange} 
     value={this.props.variantValue || ''} 
     /> 
    ); 
    } 
} 

CreateItem(variant) { 
    const unitPriceValueHash = this.props.unitPriceValueHash 
    return { 
    variant_title: variant.variant_title, 
    variant_price: variant.variant_price, 
    unit_cost: (
     <UnitCost 
     key={variant.id} 
     variantId={variant.id} 
     variantValue={unitPriceValueHash[variant.id]} 
     onUnitPriceChange={this.handleUnitPriceChange} 
     /> 
    ), 
    }; 
} 

In Bezug auf Ihre Bedenken über Fokus, reagieren in der Regel nicht das Objekt den Fokus verlieren, wenn Re-Rendering, also nicht immer, immer refokussieren ein Objekt nach ein Update aus diesem Grund.

Die einzige Zeit, die reagieren wird Fokus verlieren, ist, wenn es vollständig den aktuellen DOM-Baum verwirft und über Null beginnt. Es wird dies tun, wenn es denkt, dass ein übergeordnetes Objekt anstelle von geändert ersetzt wurde. Dies kann aufgrund einer fehlenden key Requisite oder einer key Requisite passieren, die sich geändert hat.

Sie haben nicht genügend Code für uns bereitgestellt, um dies weiter zu untersuchen. Wenn Sie mehr Hilfe benötigen, sollten Sie ein reproduzierbares Beispiel erstellen, das wir ausführen und testen können.

+0

caesay, Dank für Ihre aufschlussreichen Kommentare! Ich arbeite daran, einen Codepen zu erstellen, der das Problem reproduziert. – ByteMe

+0

In der Zwischenzeit habe ich die vollständige Codeansicht gepostet. Es wird eine Weile dauern, bis der CodePen erstellt wurde, da viele Dinge, wie zB Varianten, vom Rails-Backend kommen. – ByteMe

Verwandte Themen