Creazione del proprio componente CheckBox in React Native

Ehi Reacteros, creiamo una bella casella di controllo e la usiamo ovunque? Mooooolto... Andiamo!

Introduzione

Sono un grande fan di React e finisco per creare praticamente tutte le mie app mobili e web con esso. Mentre sto sviluppando, mi mancano alcuni componenti più personalizzabili, specialmente quelli che so che userò in altre parti del progetto (o anche in uno nuovo).
Con questo in mente, ho deciso di selezionare questa casella di controllo. E ad essere onesto, mi piace molto creare i miei componenti =).

Beh, ho detto troppo. Ora passiamo al lavoro \o/

Dipendenze

Avremo due dipendenze, icone vettoriali native di reazione e tipi prop. i link per l'installazione sono:https://github.com/oblador/react-native-vector-icons e https://github.com/facebook/prop-types

E infine, il codice.

Creiamo il nostro piccolo componente e chiamiamolo affettuosamente "CheckBox".
La shell assomiglia a questo:

import React from 'react';
import { Text, View } from "react-native" 

export default function CheckBox(props) {
  return (
   <Text>Hello World</Text>
  );
}

Il nostro componente sarà fondamentalmente un quadrato vuoto e accanto a quel quadrato un'etichetta, giusto? Cliccando sul quadrato (che al momento è vuoto), apparirà un segno di spunta e viceversa. Quindi abbiamo bisogno di un pulsante, alcune viste, testo, icone e stile. Quindi, iniziamo con le importazioni, che saranno queste:

import React from 'react';
import PropTypes from "prop-types"
import Icon from "react-native-vector-icons/FontAwesome"
import { View, TouchableOpacity, Text, StyleSheet } from 'react-native';

Affinché l'etichetta sia accanto al quadrato, dobbiamo creare un contenitore con "riga" in direzione flessibile, creiamo quindi questo stile e chiamiamolo "WrapperCheckBox".

const styles = StyleSheet.create({
  WrapperCheckBox: {
    flexDirection: "row",
    alignItems: "center"
  }
})

Cogliamo l'occasione per creare gli stili checkbox, che chiameremo "CheckBox" e l'etichetta, che chiameremo "LabelCheck". Il nostro stile finale si presenta così:

const styles = StyleSheet.create({
  CheckBox: {
    width: 25,
    height: 25,
    borderWidth: 1,
    justifyContent: "center",
    alignItems: "center"
  },
  WrapperCheckBox: {
    flexDirection: "row",
    alignItems: "center"
  },
  LabelCheck: {
    color: '#fff',
    marginLeft: 6 // Para que não fique colado ao checkbox
  }
})

Ora, riempiamo il nostro componente e mettiamo i suoi contenuti nei posti giusti. Sarà più o meno così:avremo una View del contenitore, che assumerà lo stile WrapperCheckBox; avremo un pulsante, che sarà la nostra checkbox e assumerà lo stile CheckBox; all'interno del pulsante avremo un'icona; e infine avremo l'etichetta, che sarà un Text e assumerà lo stile LabelCheck. Sembrando così:

 <View style={styles.WrapperCheckBox}>
    <TouchableOpacity style={styles.CheckBox}>
      <Icon name="check" /> 
    </TouchableOpacity>

    <Text style={styles.LabelCheck}>

    </Text>
 </View>

Finora abbiamo assemblato l'intera parte visiva del componente e ti starai chiedendo:"Ok, ora come facciamo a farlo funzionare?". Calmati! Per prima cosa, dobbiamo parlare degli oggetti di scena che riceveremo in questo componente. ecco!

Dobbiamo prevedere 6 prop per il completamento di questo componente, sono:

Sostegni Tipo Funzione
Etichetta Stringa Sarà il nome che apparirà accanto alla casella di controllo
labelStyle Oggetto Stile etichetta
iconColor Stringa Controlla il colore dell'icona
onChange Funzione Funzione che verrà richiamata quando si clicca sulla casella di controllo
valore Booleano Sarà lo stato della casella di controllo
controlla Colore Stringa Colore casella di controllo

Avendo queste informazioni, creiamo i proptype per questo componente. "Alan, cos'è questa cosa proptype?" Io spiego. Immagina di prendere un componente per mantenerlo e riceve una serie di oggetti di scena. Per aiutare, non sai nemmeno quali e quanti sono possibili. Poi diventa difficile, giusto? Questo è ciò che risolvono i tipi prop, lo "documentano" nel componente.

Dopo aver creato i proptype per il nostro componente, dovrebbe apparire così:

import React from 'react';
import PropTypes from "prop-types"
import Icon from "react-native-vector-icons/FontAwesome"
import { View, TouchableOpacity, Text, StyleSheet } from 'react-native';


export default function CheckBox(props) {
  return (
    <View style={styles.WrapperCheckBox}>
      <TouchableOpacity style={styles.CheckBox}>
        <Icon name="check" />
      </TouchableOpacity>

      <Text style={styles.LabelCheck}>

      </Text>
    </View>
  );
}

const styles = StyleSheet.create({
  CheckBox: {
    width: 25,
    height: 25,
    borderWidth: 1,
    justifyContent: "center",
    alignItems: "center"
  },
  WrapperCheckBox: {
    flexDirection: "row",
    alignItems: "center"
  },
  LabelCheck: {
    color: '#fff',
    marginLeft: 6
  }
})

CheckBox.propTypes = {
  label: PropTypes.string,
  labelStyle: PropTypes.object,
  iconColor: PropTypes.string,
  onChange: PropTypes.func,
  value : PropTypes.bool,
  checkColor : PropTypes.string 
}

Tutto bene finora, Reacteros? Quindi facciamo in modo che funzioni. Andiamo!

Logica componente

Per prima cosa, aggiorniamo il nostro componente con stili che possono essere dinamici, cioè quelli che arrivano tramite oggetti di scena.

La nostra casella di controllo può cambiare colore a seconda di ciò che viene fornito negli oggetti di scena checkColor, giusto? Sì. E come lo faremo? Bene, nota che ha già uno stile, ma dobbiamo aggiungerne uno in più. In questo caso, la proprietà style riceve un array e non un singolo oggetto. In questo modo siamo in grado di avere più oggetti di stile.

Il colore della nostra casella di controllo non è altro che il borderColor. Quindi, aggiungiamo un oggetto a questo array contenente questa proprietà insieme a un ternario, convalidando se ci sono questi oggetti di scena e, in caso contrario, mantieni il colore bianco. Sembrerà così:

 <TouchableOpacity onPress={handeChange} style={[
   styles.CheckBox,
   { borderColor: props.checkColor ? props.checkColor : '#fff' }
 ]}>

Faremo la stessa cosa per l'etichetta. Approfittando di ciò, posizionare la props.label all'interno del Text, che sarà l'etichetta ricevuta. Rimane così:

  <Text style={[styles.LabelCheck, props.labelStyle]}>
    {props.label}
  </Text>

Ora l'icona e puoi inserire un fontSize su di essa. Ricordando che, poiché non ha uno stile, non è necessario modificare la proprietà dello stile in un array. Rimane così:

<Icon name="check"
  style={{ 
    fontSize: 16,
    color: props.iconColor ? props.iconColor : '#fff'
  }}
/>

Passiamo ora alla logica principale del componente.

Innanzitutto, dobbiamo assicurarci che l'icona di controllo sia visibile solo se il valore props è vero, giusto? Per questo motivo, lo faremo con un ternario. Se vero, mostra l'icona, altrimenti non compare nemmeno. Vai fuori di qui. Arrivederci.

Sembrerà così:

{
    props.value ? <Icon name="check" style={{
       fontSize: 16,
       color: props.iconColor ? props.iconColor : '#fff'
     }}
    /> : null
}

Lo 'show' e 'not show' avverranno quando l'utente fa clic sul segno di spunta, quindi dove dovrebbe essere chiamato questo evento? Puoi parlare... No... Se hai risposto al pulsante onPress, tu... HIT \o/. Ricordi gli oggetti di scena onChange? Quindi, questa props sarà una funzione che verrà passata al componente, che in teoria cambierà lo stato del valore props. Dovremo chiamare questo tizio, quando l'utente fa clic sulla casella di controllo. "Alan, possiamo inserire questa funzione direttamente in onPress di TouchableOpacity?". Sì possiamo. Ma ricorda, può darsi che questo oggetto di scena non esista e poi l'hai visto, giusto? L'utente farà clic e BOOMMMM! È nato il nostro primo bug.

Per proteggerci da questo e tenerlo ben separato nel componente, creiamo una funzione chiamata handleChange ed eseguiamo questa convalida lì. Fondamentalmente controllerà questi oggetti di scena. Se c'è, invocherà questa funzione, altrimenti non farà nulla.

La funzione è questa:

 function handleChange() {
   const { onChange } = props;
   if (onChange) {
     return onChange();
   }
 }

Usiamo la destrutturazione per ottenere gli oggetti di scena onChange. "Per avere fantasia?" No, vedrai ad un certo punto della tua vita che questa funzionalità ES6 è di prim'ordine.

Verifichiamo se esiste davvero un onChange. Se c'è invoca, altrimenti non fare nulla. Ora chiama questa funzione nel nostro pulsante onPress.

E indovina un po':sono tutti i miei reattori! Solo quello. Il tuo componente ora dovrebbe apparire così:

import React from 'react';
import PropTypes from "prop-types"
import Icon from "react-native-vector-icons/FontAwesome"
import { View, TouchableOpacity, Text, StyleSheet } from 'react-native';




export default function CheckBox(props) {



  function handleChange() {
    const { onChange } = props;
    if (onChange) {
      return onChange();
    }
  }




  return (
    <View style={styles.WrapperCheckBox}>

      <TouchableOpacity onPress={handleChange} style={[
        styles.CheckBox,
        { borderColor: props.checkColor ? props.checkColor : '#fff' }
      ]}>

        {
          props.value ? <Icon name="check"
            style={{
              fontSize: 16,
              color: props.iconColor ? props.iconColor : '#fff'
            }}
          /> : null
        }

      </TouchableOpacity>

      <Text style={[styles.LabelCheck, props.labelStyle]}>
        {props.label}
      </Text>
    </View>
  );
}

const styles = StyleSheet.create({
  CheckBox: {
    width: 25,
    height: 25,
    borderWidth: 1,
    justifyContent: "center",
    alignItems: "center"
  },
  WrapperCheckBox: {
    flexDirection: "row",
    alignItems: "center"
  },
  LabelCheck: {
    color: '#fff',
    marginLeft: 6
  }
})

CheckBox.propTypes = {
  label: PropTypes.string,
  labelStyle: PropTypes.object,
  iconColor: PropTypes.string,
  onChange: PropTypes.func,
  value: PropTypes.boolean,
  checkColor: PropTypes.string
}

"Ma Alan, te ne vai senza lasciarci un esempio di utilizzo?" Certo. Collegare:

import React, { useState } from "react";
import { View, StyleSheet, StatusBar } from "react-native"
import CheckBox from "./components/checkbox"




export default function App() {

  const [check, setCheck] = useState(false)

  function handleCheck() {
    setCheck(!check);
  }


  return (
    <>
      <StatusBar backgroundColor="#f47e10" />
      <View style={styles.Container}>

        {/* Esse é o nosso lindo checkBox */}
        <CheckBox
          label="Esse é um checkbox"
          labelStyle={{ color: '#fff', fontSize: 16 }}
          iconColor="#fff"
          checkColor="#fff"
          value={check}
          onChange={handleCheck}
        />


      </View>
    </>
  )
}

const styles = StyleSheet.create({
  Container: {
    flex: 1,
    justifyContent: "flex-start",
    alignItems: "flex-start",
    backgroundColor: '#f47e10',
    padding: 20
  }
})

Finalmente

Grazie per aver letto fino a qui. Questo è stato il mio primo post e spero sia il primo di molti. Grazie Reacteroooooss!!!!