Mise en ligne : dimanche 7 janvier 2024
Cet article est la deuxième partie d'une série qui est consacrée à la maîtrise d'Expo Router, dans sa deuxième version. Voici deux liens qui peuvent vous être utiles :
Vous pourriez, par exemple, avoir besoin d'aller sur une autre page, après avoir réalisé une action dans une fonction, et dans ce cas, l'utilisation du hook router est nécessaire.
Son utilisation est d'ailleurs très similaire au hook useRouter de Next.js
Pour pouvoir tester sur le navigateur, nous allons modifier la propriété web
du fichier app.json, en ajoutant la ligne "bundler": "metro"
:
app.json"web": {
"bundler": "metro",
"favicon": "./assets/favicon.png"
},
Lançons notre serveur web avec la commande npm run web
Nous allons nous amuser dans la page settings
Le push
rajoute une nouvelle page à la stack
actuelle, ce qui signifie que l'on pourra revenir en arrière, à l'aide des boutons de redirections de notre navigateur.
Modifions notre page settings
:
app/settings/index.tsximport { router } from 'expo-router';
import { View, Text, StyleSheet, Button } from 'react-native';
export default function SettingsScreen() {
const handlePush = () => {
router.push('/');
};
return (
<View style={styles.container}>
<Text style={styles.title}>Settings</Text>
<Button
title="Push"
onPress={handlePush}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
padding: 24,
gap: 12,
},
title: {
fontSize: 32,
fontWeight: 'bold',
},
});
Ce bouton permet de revenir sur la page d'accueil, mais vu que nous avons utiliser push
, ça rajoute notre page à la stack actuelle.
Nous pouvons également transmettre un objet contenant le pathname
et les params
, comment nous le ferions avec un composant Link.
Par exemple, un bouton pourrait renvoyer vers une page de blog avec un slug :
app/settings/index.tsxconst handlePushWithParams = () => {
router.push({
pathname: '/blog/[slug]',
params: { slug: 'super-article-de-blog' },
});
};
app/settings/index.tsx<Button
title="Push avec params"
onPress={handlePushWithParams}
/>
Le replace
remplace la route actuelle dans la stack, ce qui signifie, bien évidemment, que vous ne pourrez pas revenir en arrière dans votre navigation, ça peut être utile, par exemple, après une authentification.
Créons une nouvelle fonction handleReplace
avec le bouton associé :
app/settings/index.tsxconst handleReplace = () => {
router.replace('/');
};
app/settings/index.tsx<Button
title="Replace"
onPress={handleReplace}
/>
Si, on click sur notre nouveau bouton, on constate bien que notre nouvelle route remplace l'ancienne.
Nous pouvons implémenter le retour sur la page précédente avec back
:
Ajoutons la fonction handleBack
et le bouton associé :
app/settings/index.tsxconst handleBack = () => {
router.back();
};
app/settings/index.tsx<Button
title="Replace"
onPress={handleReplace}
/>
Désormais, nous avons un bouton qui permet de revenir en arrière. Affinons un peu notre design pour avoir un vrai bouton Back. Modifions notre bouton :
app/settings/index.tsx<Pressable
onPress={handleBack}
style={styles.buttonBack}>
<Ionicons
name="arrow-back"
size={24}
color="black"
/>
</Pressable>
Ajoutons le style dans le StyleSheet.create, en ajoutant également la position absolute dans le container :
app/settings/index.tsconst styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
padding: 24,
gap: 12,
position: 'relative',
},
title: {
fontSize: 32,
fontWeight: 'bold',
},
buttonBack: {
position: 'absolute',
top: 12,
left: 12,
},
});
N'oublions pas d'ajouter notre import pour utiliser notre icone :
app/settings/index.tsximport { Ionicons } from '@expo/vector-icons';
C'est beaucoup mieux comme ça 😉.
Nous pouvons vérifier que nous pouvons revenir en arrière, pour par exemple, cacher ou désactiver un bouton, si l'action de retour n'est pas possible. Pour tester cette fonctionnalité, nous allons externaliser notre composant BackButton, en créant un bouton réutilisable.
components/back-button.tsximport { Pressable, StyleSheet } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { router } from 'expo-router';
export default function BackButton() {
const handleBack = () => {
router.back();
};
return (
<Pressable
onPress={handleBack}
style={styles.buttonBack}>
<Ionicons
name="arrow-back"
size={24}
color="black"
/>
</Pressable>
);
}
const styles = StyleSheet.create({
buttonBack: {
position: 'absolute',
top: 24,
left: 24,
},
});
Importons ce bouton dans la page de settings, mais également dans la page d'accueil. Modifions notre bouton, pour prendre en charge le canGoBack :
components/back-button.tsximport { Pressable, StyleSheet } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { router } from 'expo-router';
export default function BackButton() {
const handleBack = () => {
router.back();
};
return (
<Pressable
disabled={!router.canGoBack()}
onPress={handleBack}
style={styles.buttonBack}>
<Ionicons
name="arrow-back"
size={24}
color={router.canGoBack() ? 'black' : 'lightgray'}
/>
</Pressable>
);
}
const styles = StyleSheet.create({
buttonBack: {
position: 'absolute',
top: 24,
left: 24,
},
});
Dans la page d'accueil, pensez bien à modifier les styles du container, en ajoutant la propriété `"position":"absolute", et en mettant le bouton dans la première View. On voit bien que lorsqu'il n'est pas possible de revenir en arrière, le bouton est grisé et non clickable.
Le setParams
permet de gérer les query de nos urls.
Dans notre page de settings, nous pourrions ajoutons une gestion du darkmode.
Créons un type pour gérer les différents états :
app/settings/index.tsxtype Mode = "light" | "dark"
Nous utiliserons le hook useGlobalSearchParams pour avoir accès aux searchParams.
app/settings/index.tsximport { useGlobalSearchParams } from 'expo-router';
app/settings/index.tsxconst { mode } = useGlobalSearchParams();
Nous créons ensuite une fonction switchMode
qui nous permettra de changer de mode :
app/settings/index.tsxconst switchMode = () => {
const newMode = mode === 'light' ? 'dark' : 'light';
router.setParams({ mode: newMode });
};
Nous allons Créer un Pressable qui s'adpatera au contexte (affichage et action).
app/settings/index.tsx<Pressable onPress={switchMode}>
<Text> {`Switch to ${mode === 'light' ? 'Dark' : 'Light'} Mode`} </Text>
</Pressable>
Nous voyons bien que tout fonctionne correctement :
searchParams
de notre url sont bien modifiés.Il est important de noté, que setParams agit comme un state, et effectue un rerender du composant.