JS, React & React Native

Utilisation du DatePicker avec React Native

April 15, 2020

Dans les formulaires, il est parfois indispensable d’enregistrer une date et une heure (dans un formulaire de réservation par exemple). Cela peut paraître assez simple au premier abort, mais pour ma part, cela a été un peu plus difficile que prévu. J’y ai pas passé des heures non plus, mais j’ai quand même perdu un peu de temps.

Mise en place de la page de base

Pour gérer l’affichage, j’ai décidé d’utiliser un champs pour l’heure et un champs pour la date:

  • Quand on clique sur la date, on change la date
  • Quand on clique sur l’heure, on change l’heure

Ce sont les appuis sur l’un ou l’autre de ces champs textes qui va nous permettre de faire apparaître me datetimepicker soit pour changer la date, soit pour changer l’heure.

La page de base va donc ressemble à ça

import React, { useState } from 'react';
import { Text, View, StyleSheet } from 'react-native';
import DateTimePicker from '@react-native-community/datetimepicker'

export default function App() {
  const [date, setDate] = useState(new Date())

  return (
    <View style={styles.container}>
      <Text style={styles.text}>
        {`${('0' + date.getDate()).slice(-2)}/${('0' + date.getMonth()).slice(-2)}/${date.getFullYear()}`}
      </Text>
      <Text style={styles.text}>
        {`${('0' + date.getHours()).slice(-2)}:${('0' + date.getMinutes()).slice(-2)}`}
      </Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-around',
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
  text :{
    fontSize: 14,
    borderColor: 'blue',
    borderWidth: 2,
    borderRadius: 15,
    padding: 20
  }
});

Ajout du datetimepicker

installation du module

Pour commencer, on va d’abord avoir besoin d’importer le bon module

npm install @react-native-community/satetimepicker --save

Ensuite, pour l’utiliser, on doit juste l’importer

import DateTimePicker from '@react-native-community/datetimepicker'

Ajout du composant

C’était la partie très intuitive, maintenant on va passer sur ce qui l’est un peu moins. Maintenant, on va commencer par l’afficher sur notre page:

<DateTimePicker
    value={new Date()}
/>

Le problème quand on fait ça, c’est qu’il s’affichage dès qu’on charge la page et du coup c’est plutôt moche.

Gestion de l’affichage du datetimepicker

l’afficher ou non

On va commencer par déclarer une variable d’état

const [visible, setVisible] = useEffect(false)

On va intégrer notre variable dans la page

{visible &&
    <DateTimePicker
        value={new Date()}
    />
}

On va ensuite créer une fonction pour mettre à jour la variable

const showPicker = () => {
    setVisible(true)
}

Et nous allons le faire apparaitre dès que l’on clique sur la date ou l’heure

    <View style={styles.container}>
      <Text style={styles.text} onPress={showPicker}>
        {`${('0' + date.getDate()).slice(-2)}/${('0' + date.getMonth()).slice(-2)}/${date.getFullYear()}`}
      </Text>
      <Text style={styles.text} onPress={showPicker}>
        {`${('0' + date.getHours()).slice(-2)}:${('0' + date.getMinutes()).slice(-2)}`}
      </Text>
    </View>

Choisir si on veut afficher la date ou l’heure

Actuellement, le fait de cliquer sur la date ou l’heure, nous fait apparaître la même chose. Il faut donc mettre à jour notre composant selon ce que nous souhaitons afficher. Cela se fait à l’aide la propriété “mode”. Si on souhaite chaner la date, on met ‘date’, si on souhaite changer l’heure, on met ‘time’.

On commence par créer une variable d’état

const [mode, setMode] = useState('')

On va donc créer deux fonctions supplémentaires

const showDate = () => {
    setMode('date')
    showPicker()
}

const showTime = () => {
    setMode('time')
    showPicker()
}

et mettre à jour les fonctions appelées dans les

    <View style={styles.container}>
      <Text style={styles.text} onPress={showDate}>
        {`${('0' + date.getDate()).slice(-2)}/${('0' + date.getMonth()).slice(-2)}/${date.getFullYear()}`}
      </Text>
      <Text style={styles.text} onPress={showTime}>
        {`${('0' + date.getHours()).slice(-2)}:${('0' + date.getMinutes()).slice(-2)}`}
      </Text>
    </View>

Mettre à jour les champs

Il ne nous reste plus qu’à mettre à jour les champs une fois que nous avons selectionné les valeurs voulues.

const dateChange = (event, selectedDate) => {
    const currentDate = selectedDate || date
    setVisible(false)
    setDate(currentDate)
}

Dans le code, on récupère la valeur qui a été choisie. Dans le cas où aucune valeur n’a été choisie, on reprend la valeur qu’il y avait avant. Ensuite, on repasse le ‘visible’ à false pour que le datetimePicker ne s’affiche plus. Et enfin, on met à jour la variable d’état.

code complet du composant

import React, { useState } from 'react';
import { Platform, Text, View, StyleSheet } from 'react-native';
import DateTimePicker from '@react-native-community/datetimepicker'

export default function App() {
  const [date, setDate] = useState(new Date())
  const [visible, setVisible] = useState(false)
  const [mode, setMode] = useState('')

  const showPicker = () => {
    setVisible(true)
  }

  const showDate = () => {
    setMode('date')
    showPicker()
  }

  const showTime = () => {
    setMode('time')
    showPicker()
  }

  const dateChange = (event, selectedDate) => {
        const currentDate = selectedDate || date
        setVisible(false)
        setDate(currentDate)
  }

  return (
    <View style={styles.container}>
      <Text style={styles.text} onPress={showDate}>
        {`${('0' + date.getDate()).slice(-2)}/${('0' + date.getMonth()).slice(-2)}/${date.getFullYear()}`}
      </Text>
      <Text style={styles.text} onPress={showTime}>
        {`${('0' + date.getHours()).slice(-2)}:${('0' + date.getMinutes()).slice(-2)}`}
      </Text>
      { visible &&
        <DateTimePicker
          value={date}
          mode={mode}
          onChange={dateChange}
        />
      }
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-around',
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
  text :{
    fontSize: 14,
    borderColor: 'blue',
    borderWidth: 2,
    borderRadius: 15,
    padding: 20
  }
});