Maison > interface Web > js tutoriel > Comment créer des composants d'interface utilisateur à type forcé dans React Native à l'aide de @shopify/restyle

Comment créer des composants d'interface utilisateur à type forcé dans React Native à l'aide de @shopify/restyle

Mary-Kate Olsen
Libérer: 2024-12-02 09:05:15
original
255 Les gens l'ont consulté

Cela fait un certain temps que je n'ai pas écrit d'article technique sur mon blog, et en voici un nouveau sur la création de composants d'interface utilisateur à type forcé dans React Native avec @shopify/restyle et expo.

@shopify/restyle est une puissante bibliothèque de styles pour React Native qui apporte sécurité et cohérence des types à vos composants d'interface utilisateur. Contrairement aux approches de style traditionnelles, Restyle vous permet de créer une configuration de thème centralisée qui applique les principes du système de conception dans l'ensemble de votre application.

Commencer

Configuration du projet

  • Configurez votre projet natif React à l'aide d'expo
npx create-expo-app@latest
Copier après la connexion
Copier après la connexion
  • Accédez au répertoire de votre projet et installez le package @shopify/restyle à l'aide d'expo
cd /path/to/project
npx expo install @shopify/restyle
Copier après la connexion

Créer votre thème

Créez un fichier theme.tsx pour définir votre système de conception :

touch theme.tsx
Copier après la connexion
  • Copiez et collez la configuration du thème par défaut
import {createTheme} from '@shopify/restyle';

const palette = {
  purpleLight: '#8C6FF7',
  purplePrimary: '#5A31F4',
  purpleDark: '#3F22AB',

  greenLight: '#56DCBA',
  greenPrimary: '#0ECD9D',
  greenDark: '#0A906E',

  black: '#0B0B0B',
  white: '#F0F2F3',
};

const theme = createTheme({
  colors: {
    mainBackground: palette.white,
    cardPrimaryBackground: palette.purplePrimary,
  },
  spacing: {
    s: 8,
    m: 16,
    l: 24,
    xl: 40,
  },
  textVariants: {
    header: {
      fontWeight: 'bold',
      fontSize: 34,
    },
    body: {
      fontSize: 16,
      lineHeight: 24,
    },
    defaults: {
      // We can define a default text variant here.
    },
  },
});

export type Theme = typeof theme;
export default theme;
Copier après la connexion

Implémentation du fournisseur de thème

Mettez à jour votre app/_layout.tsx :

import { DarkTheme, DefaultTheme } from "@react-navigation/native";
import { useFonts } from "expo-font";
import { Stack } from "expo-router";
import * as SplashScreen from "expo-splash-screen";
import { StatusBar } from "expo-status-bar";
import { useEffect } from "react";
import "react-native-reanimated";

import { ThemeProvider } from "@shopify/restyle";
import theme from "@/theme";

// Prevent the splash screen from auto-hiding before asset loading is complete.
SplashScreen.preventAutoHideAsync();

export default function RootLayout() {
  const [loaded] = useFonts({
    SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"),
  });

  useEffect(() => {
    if (loaded) {
      SplashScreen.hideAsync();
    }
  }, [loaded]);

  if (!loaded) {
    return null;
  }

  return (
    <ThemeProvider theme={theme}>
      <Stack>
        <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
        <Stack.Screen name="+not-found" />
      </Stack>
      <StatusBar>



<h2>
  
  
  Creating Reusable Components
</h2>

<h3>
  
  
  Text Component
</h3>



<pre class="brush:php;toolbar:false">touch components/Text.tsx
Copier après la connexion
// In components/Text.tsx

import {createText} from '@shopify/restyle';
import {Theme} from '../theme';

export const Text = createText<Theme>();

Copier après la connexion

Utilisons-le sur notre écran d'accueil

import { Text } from "@/components/Text";
import { SafeAreaView } from "react-native-safe-area-context";

export default function HomeScreen() {
  return (
    <SafeAreaView>
      <Text margin="m" variant="header">
        This is the Home screen. Built using @shopify/restyle.
      </Text>
    </SafeAreaView>
  );
}

Copier après la connexion

Comme vous pouvez le voir dans le code ci-dessus, nous transmettons la marge sous forme de « m » au lieu d'un nombre. Nous obtenons la valeur de notre fichier theme.tsx.

// ./theme.tsx

const theme = createTheme({
  spacing: {
    s: 8,
    m: 16, // margin="m"
    l: 24,
    xl: 40,
  },
  textVariants: {
    header: { // our text header variant
      fontWeight: 'bold',
      fontSize: 34,
    },
    body: {
      fontSize: 16,
      lineHeight: 24,
    },
  },
    // ...rest of code
  },
});
Copier après la connexion

Voici à quoi ressemblera la vue de notre page d'accueil

How to build type-enforced UI components in React Native using @shopify/restyle

Composant de chargeur squelette

Construisons une carte Skeleton Loader

touch components/SkeletonLoader.tsx
Copier après la connexion
// components/SkeletonLoader.tsx

import {
  BackgroundColorProps,
  createBox,
  createRestyleComponent,
  createVariant,
  spacing,
  SpacingProps,
  VariantProps,
} from "@shopify/restyle";
import { Theme } from "@/theme";
import { View } from "react-native";

const Box = createBox<Theme>();

type Props = SpacingProps<Theme> &
  VariantProps<Theme, "cardVariants"> &
  BackgroundColorProps<Theme> &
  React.ComponentProps<typeof View>;

const CardSkeleton = createRestyleComponent<Props, Theme>([
  spacing,
  createVariant({ themeKey: "cardVariants" }),
]);

const SkeletonLoader = () => {
  return (
    <CardSkeleton variant="elevated">
      <Box
        backgroundColor="cardPrimaryBackground"
        height={20}
        marginBottom="s"
        width="70%"
        overflow="hidden"
        borderRadius={"m"}
      >
      </Box>

      <Box
        backgroundColor="cardPrimaryBackground"
        height={100}
        marginBottom="s"
        width="90%"
        overflow="hidden"
        borderRadius={"m"}
      >
      </Box>
      <Box
        backgroundColor="cardPrimaryBackground"
        height={50}
        marginBottom="s"
        width="70%"
        overflow="hidden"
        borderRadius={"m"}
      >
      </Box>
    </CardSkeleton>
  );
};

export default SkeletonLoader;

Copier après la connexion
  • Nous créons une nouvelle boîte en tant que composant prédéfini à partir du package @shopify/restyle et c'est ainsi que nous créerons la boîte squelette
const Box = createBox<Theme>();
Copier après la connexion
  • Créez un nouveau composant CardSkeleton en utilisant createStyleComponent pour créer un composant personnalisé et nous avons passé les accessoires qui sont l'espacement et les cardVariants que nous devons définir dans notre fichier theme.tsx.
type Props = SpacingProps<Theme> &
  VariantProps<Theme, "cardVariants"> &
  BackgroundColorProps<Theme> &
  React.ComponentProps<typeof View>;

const CardSkeleton = createRestyleComponent<Props, Theme>([
  spacing,
  createVariant({ themeKey: "cardVariants" }),
]);
Copier après la connexion
  • Créez un composant SkeletonLoader pour restituer notre composant Skelton Card
// components/SkeletonLoader.tsx

export const SkeletonLoader = () => {
  return (
    <CardSkeleton variant="elevated">
      <Box
        backgroundColor="cardPrimaryBackground"
        height={20}
        marginBottom="s"
        width="70%"
        overflow="hidden"
        borderRadius={"m"}
      ></Box>

      <Box
        backgroundColor="cardPrimaryBackground"
        height={100}
        marginBottom="s"
        width="90%"
        overflow="hidden"
        borderRadius={"m"}
      ></Box>
      <Box
        backgroundColor="cardPrimaryBackground"
        height={50}
        marginBottom="s"
        width="70%"
        overflow="hidden"
        borderRadius={"m"}
      ></Box>
    </CardSkeleton>
  );
};

Copier après la connexion

Il nous reste une chose pour que cela fonctionne, mettre à jour le fichier theme.tsx pour avoir cardVariants

const theme = createTheme({
  colors: {
    // Add Black Color to use it later on
    black: palette.black,
  },
  // Add Border Radius Variants
  borderRadii: {
    s: 4,
    m: 10,
    l: 25,
    xl: 75,
  },
  // Add Card Variants
  cardVariants: {
    elevated: {
      shadowColor: "black",
      shadowOffset: { width: 0, height: 2 },
      shadowOpacity: 0.1,
      shadowRadius: 4,
      elevation: 3,
      borderRadius: "m",
    },
    defaults: {
      padding: "m",
      borderRadius: "m",
    },
  },
});

Copier après la connexion

C'est super, mais animons notre composant

// components/SkeletonLoader.tsx

const ShimmerAnimation = () => {
  const shimmerTranslate = useRef(new Animated.Value(0)).current;

  useEffect(() => {
    Animated.loop(
      Animated.timing(shimmerTranslate, {
        toValue: 1,
        duration: 1500,
        useNativeDriver: true,
      })
    ).start();
  }, [shimmerTranslate]);

  const translateX = shimmerTranslate.interpolate({
    inputRange: [0, 1],
    outputRange: [-300, 300],
  });

  return (
    <Animated.View
     >



<p>and let’s use it in our Skeleton Loader Component<br>
</p>

<pre class="brush:php;toolbar:false">// components/SkeletonLoader.tsx

export const SkeletonLoader = () => {
  return (
    <CardSkeleton variant="elevated">
      <Box
        backgroundColor="cardPrimaryBackground"
        height={20}
        marginBottom="s"
        width="70%"
        overflow="hidden"
        borderRadius={"m"}
      >
        <ShimmerAnimation />
      </Box>

      <Box
        backgroundColor="cardPrimaryBackground"
        height={100}
        marginBottom="s"
        width="90%"
        overflow="hidden"
        borderRadius={"m"}
      >
        <ShimmerAnimation />
      </Box>
      <Box
        backgroundColor="cardPrimaryBackground"
        height={50}
        marginBottom="s"
        width="70%"
        overflow="hidden"
        borderRadius={"m"}
      >
        <ShimmerAnimation />
      </Box>
    </CardSkeleton>
  );
};

Copier après la connexion

Et voici le code complet du composant :

// components/SkeletonLoader.tsx

import { useEffect, useRef } from "react";
import { Animated } from "react-native";
import {
  BackgroundColorProps,
  createBox,
  createRestyleComponent,
  createVariant,
  spacing,
  SpacingProps,
  VariantProps,
} from "@shopify/restyle";
import { Theme } from "@/theme";
import { View } from "react-native";

const Box = createBox<Theme>();

const ShimmerAnimation = () => {
  const shimmerTranslate = useRef(new Animated.Value(0)).current;

  useEffect(() => {
    Animated.loop(
      Animated.timing(shimmerTranslate, {
        toValue: 1,
        duration: 1500,
        useNativeDriver: true,
      })
    ).start();
  }, [shimmerTranslate]);

  const translateX = shimmerTranslate.interpolate({
    inputRange: [0, 1],
    outputRange: [-300, 300],
  });

  return (
    



Et voila, we made a skeleton loader card using @shopify/restyle using

How to build type-enforced UI components in React Native using @shopify/restyle

Support for dark mode

Let’s start with adding dark theme configuration, in your theme.tsxfile

// theme.tsx

export const darkTheme: Theme = {
  ...theme,
  colors: {
    ...theme.colors,
    mainBackground: palette.white,
    cardPrimaryBackground: palette.purpleDark,
    greenPrimary: palette.purpleLight,
  },
  textVariants: {
    ...theme.textVariants,
    defaults: {
      ...theme.textVariants.header,
      color: palette.purpleDark,
    },
  },
Copier après la connexion

Ajoutez notre configuration de thème sombre dans la mise en page de notre application en l'ajoutant à notre fichier layout.tsx

npx create-expo-app@latest
Copier après la connexion
Copier après la connexion
  • En fonction du schéma de couleurs, utilisez le thème clair par défaut ou en mode sombre, utilisez la configuration darkTheme définie dans le fichier theme.tsx
 // app/_layout.tsx

 importer le thème, { darkTheme } depuis "@/theme" ;

 //... reste du code

    <ThemeProvider theme={colorSchema === "dark" ? darkTheme : thème}>
      <Pile>
        <Stack.Screen name="(tabs)" options={{ headerShown : false }} />
        <Stack.Screen name=" not-found" />
      </Pile>
      <Barre d'état>



<p>Voici les modes sombre et clair.</p>

<p><img src="https://img.php.cn/upload/article/000/000/000/173310152340178.jpg" alt="How to build type-enforced UI components in React Native using @shopify/restyle"></p>

<p><img src="https://img.php.cn/upload/article/000/000/000/173310152557660.jpg" alt="How to build type-enforced UI components in React Native using @shopify/restyle"></p>

<p>Et voilà, nous avons réussi à créer un composant d'interface utilisateur de type forcé à l'aide du package @shopify/restyle</p>

<p>Merci :)</p>


          

            
        
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal