2017-08-17 9 views
2

Es gibt eine Best Practice, um etwas wie das Folgende in React zu vereinfachen?Vereinfachen wiederholten Code in React

getInitialState: function() { 
    return { 
    checkbox1: false, 
    checkbox2: false, 
    checkbox3: false, 
    ... 
    }; 
}, 

selectCheckbox1: function() { 
    this.setState({ 
    checkbox1: !this.state.checkbox1 
    }); 
}, 

selectCheckbox2: function() { 
    this.setState({ 
    checkbox2: !this.state.checkbox2 
    }); 
}, 

selectCheckbox3: function() { 
    this.setState({ 
    checkbox3: !this.state.checkbox3 
    }); 
}, 

... 

render: function() { 
    return (
    <div> 
     <input type="checkbox" checked={this.state.checkbox1} onChange={this.selectCheckbox1} /> 
     <input type="checkbox" checked={this.state.checkbox2} onChange={this.selectCheckbox2} /> 
     <input type="checkbox" checked={this.state.checkbox3} onChange={this.selectCheckbox3} /> 
     ... 
    </div> 
); 
} 

Zum Beispiel kann ich ein Array für den Staat statt einzelner Felder verwenden und eine generische Funktion erstellen, die einen Index Parameter nimmt die Checkbox zu unterscheiden zu aktualisieren:

const Checkboxes = React.createClass({ 
    getInitialState: function() { 
    return { 
     checkboxes: [false, false, false, ...] 
    }; 
    }, 

    selectCheckbox: function (index) { 
    let checkboxes = this.state.checkboxes.slice(); 
    checkboxes[index] = !checkboxes[index]; 
    this.setState({ 
     checkboxes: checkboxes 
    }); 
    }, 

    render: function() { 
    return (
     <div> 
     <input type="checkbox" checked={this.state.checkboxes[0]} onChange={() => this.selectCheckbox(0)} /> 
     <input type="checkbox" checked={this.state.checkboxes[1]} onChange={() => this.selectCheckbox(1)} /> 
     <input type="checkbox" checked={this.state.checkboxes[2]} onChange={() => this.selectCheckbox(2)} /> 
     ... 
     </div> 
    ); 
    } 
}); 

Ich bin neu in Reagieren Sie und JavaScript, also weiß ich nicht genau die Kompromisse, die hier hinter den Kulissen geschehen. Ist die zweite eine Verbesserung gegenüber der ersten? Welches ist bevorzugt und warum?

+0

Diese Frage ungelöst zeigt noch. Ist es? – jonahe

Antwort

1

Ich würde so etwas tun:

class App extends Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     checkboxes: { 
     cheese: false, 
     lettuce: false, 
     tomatoe: false 
     } 
    }; 
    } 

    handleChange = e => { 
    const checkboxId = e.target.id; 
    this.setState({ 
     checkboxes: { 
     ...this.state.checkboxes, 
     [checkboxId]: !this.state.checkboxes[checkboxId] 
     } 
    }); 
    }; 

    render() { 
    return (
     <div> 
     {Object.entries(this.state.checkboxes).map(([key, val]) => { 
      return (
      <div key={key}> 
       <input 
       type="checkbox" 
       checked={val} 
       id={key} 
       onChange={this.handleChange} 
       /> 
       <label> 
       {key} 
       </label> 
      </div> 
     ); 
     })} 
     </div> 
    ); 
    } 
} 

Diese Dinge deutlicher und leichter zu folgen macht und hat den zusätzlichen Vorteil, nicht eine neue anonyme Funktion jedes Mal, wenn Sie machen zu schaffen.

+0

Was sind die Nachteile beim Erstellen einer neuen anonymen Funktion bei jedem Rendern? Wann werden sie Müll gesammelt? –

+1

@JoshBroadhurst Es ist eine bewährte Methode, der zugrunde liegenden Komponente zu erlauben, Requisiten in 'shouldComponentUpdate' zu ​​vergleichen. Anonymous Funktionen werden immer anders – thedude

+0

ok, hab es. Vielen Dank. Sie haben immer noch eine anonyme Funktion in Ihrem Map-Aufruf ('([key, val]) => {...}'), aber das wird nicht als Prop angegeben. Wie wirkt sich diese anonyme Funktion auf den Renderzyklus aus? –

3

Zweite ist definitiv besser Ansatz als die erste. Sie können damit sicher gehen.

Abgesehen davon können Sie das Kontrollkästchen auch rendern, ohne sie jedes Mal in der Renderfunktion zu wiederholen, indem Sie Array-Map verwenden.

render: function() { 
    return (
     <div> 
     {this.state.checkboxes.map((c, i) => { 
      return (
       <input key={i} type="checkbox" checked={c} onChange={() => this.selectCheckbox(i)} /> 
      ); 
     })} 
     </div> 
    ); 
    } 
1

Ich bevorzuge die Kontrollkästchen (in einem Objekt, nicht ein Array), wie in Ihrem ersten Beispiel. Das kann jedoch je nach Anwendungsfall variieren. Wenn sie als Array unbenannt sind, wie es Prakash-sharma herausstellt, bieten sie den Vorteil, dass sie über sie abgebildet werden können.

Dies ist, wie ich es tun würde die Duplizierung der Rückruffunktionsdeklarationen (ohne Speicherung der Checkbox Werte in einem Array) zu reduzieren:

const Checkboxes = React.createClass({ 
    getInitialState: function() { 
    return { 
     checkbox1: false, 
     checkbox2: false, 
     checkbox3: false 
    }; 
    }, 

    selectCheckbox: function (checkboxNr) { 
    // return a callback with the checkboxNr set 
    return() => { 
     this.setState({ 
     [checkboxNr]: !this.state[checkboxNr] 
     }); 
    } 
    }, 

    render: function() { 
    const {checkboxes1, checkboxes2, checkboxes3} = this.state; 
    return (
     <div> 
     <input type="checkbox" checked={checkboxes1} onChange={ this.selectCheckbox("checkbox1") } /> 
     <input type="checkbox" checked={checkboxes2} onChange={ this.selectCheckbox("checkbox2") } /> 
     <input type="checkbox" checked={checkboxes3} onChange={ this.selectCheckbox("checkbox3") } /> 
     </div> 
    ); 
    } 
}); 
+0

Können Sie diese Syntax erklären:' const {checkbox1, checkbox2, checkbox3} = this.state; ' –

+0

Hat die Rückgabe einer anonymen Funktion aus einer benannten Funktion für onChange prop die gleiche Garbage Collection Performance-Probleme wie die Verwendung anonymer Funktionen direkt in OnChange Prop? –

+1

@JoshBroadhurst. Sicher, vielleicht hätte ich das erwähnen sollen. Es ist [ES6 Destrukturierung] (http://exploringjs.com/es6/ch_destructuring.html#sec_overview-destrukturing), in diesem Fall für Objekte. '' this.state'' ist ein Objekt mit mehreren Eigenschaften. Mit der von Ihnen zitierten Zeile wählen wir die Eigenschaften aus, die den Kontrollkästchen checkbox1, checkbox2 und checkbox3 entsprechen.Sie stehen dann als Variablen im Bereich zur Verfügung. Es entspricht dem Schreiben 'const checkbox1 = this.state.checkbox1; const checkbox2 = this.state.checkbox2' etc. – jonahe