2017-08-17 1 views
2

Il existe une bonne pratique pour simplifier quelque chose comme ce qui suit dans React?Simplifier le code répété dans 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> 
); 
} 

Par exemple, je peux utiliser un tableau pour l'état au lieu des champs individuels et créer une fonction générique qui prend un paramètre d'index pour distinguer les case à cocher pour mettre à jour:

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

Je suis nouveau Réagissez et JavaScript donc je ne sais pas exactement les compromis qui se passent dans les coulisses ici. La seconde est-elle une amélioration par rapport à la première? Lequel est préféré et pourquoi?

+0

Cette question montre toujours aussi irrésolu. Est-ce? – jonahe

Répondre

1

je ferais quelque chose comme ceci:

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

Cela rend les choses plus explicites et plus facile à suivre et a l'avantage de ne pas créer une nouvelle fonction anonyme à chaque fois que vous rendez.

+0

Quels sont les inconvénients de la création d'une nouvelle fonction anonyme sur chaque rendu? quand sont-ils ramassés? –

+1

@JoshBroadhurst Il est recommandé d'autoriser le composant sous-jacent à comparer les accessoires dans 'shouldComponentUpdate'. Les fonctions anonymes seront toujours différentes – thedude

+0

ok, got it. Merci. vous avez toujours une fonction anonyme dans votre appel de carte ('([key, val]) => {...}') mais cela n'est pas passé comme un accessoire. comment cette fonction anonyme affecte-t-elle le cycle de rendu? –

3

Deuxième est définitivement meilleure approche alors le premier. Vous pouvez y aller en toute sécurité. En dehors de cela, vous pouvez également rendre la case à cocher sans les répéter chaque fois dans la fonction de rendu en utilisant la carte de tableau.

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

Je préfère avoir les cases à cocher nommées (dans un objet, pas un tableau), comme dans votre premier exemple. Mais cela pourrait varier selon le cas d'utilisation. Le fait de les indiquer sans nom comme tableau fait, comme le souligne Prakash-sharma, l'avantage d'être capable de les cartographier.

Voilà comment je ferais pour réduire la duplication des déclarations de fonctions de rappel (sans mémoriser les valeurs de cases à cocher dans un tableau):

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

Pouvez-vous expliquer cette syntaxe:' const {checkbox1, checkbox2, checkbox3} = this.state; ' –

+0

Retourne une fonction anonyme d'une fonction nommée pour onChange mêmes problèmes de performance de récupération de place que l'utilisation de fonctions anonymes directement dans onChange prop? –

+1

@JoshBroadhurst. Bien sûr, peut-être que j'aurais dû le mentionner. C'est [ES6 destructuring] (http://exploringjs.com/es6/ch_destructuring.html#sec_overview-destructuring), dans ce cas pour les objets. '' this.state'' est un objet contenant plusieurs propriétés. Avec la ligne que vous avez citée, nous sélectionnons les propriétés qui correspondent aux noms checkbox1, checkbox2 et checkbox3.Ils sont ensuite disponibles en tant que variables dans la portée. C'est l'équivalent de l'écriture 'const checkbox1 = this.state.checkbox1; const checkbox2 = this.state.checkbox2' etc – jonahe