Rumah >hujung hadapan web >tutorial js >Cara membina komponen UI yang dikuatkuasakan jenis dalam React Native menggunakan @shopify/restyle

Cara membina komponen UI yang dikuatkuasakan jenis dalam React Native menggunakan @shopify/restyle

Mary-Kate Olsen
Mary-Kate Olsenasal
2024-12-02 09:05:15250semak imbas

Sudah agak lama saya tidak menulis siaran teknikal di blog saya, dan berikut ialah yang baharu tentang membina komponen UI yang dikuatkuasakan jenis dalam React Native dengan @shopify/restyle dan ekspo.

@shopify/restyle ialah perpustakaan penggayaan yang berkuasa untuk React Native yang membawa keselamatan dan ketekalan jenis kepada komponen UI anda. Tidak seperti pendekatan penggayaan tradisional, Restyle membolehkan anda membuat konfigurasi tema terpusat yang menguatkuasakan prinsip sistem reka bentuk merentas keseluruhan aplikasi anda.

Bermula

Persediaan Projek

  • Sediakan projek asli bertindak balas anda menggunakan ekspo
npx create-expo-app@latest
  • Pergi ke direktori projek anda dan pasang pakej @shopify/restyle menggunakan ekspo
cd /path/to/project
npx expo install @shopify/restyle

Mencipta Tema Anda

Buat fail theme.tsx untuk menentukan sistem reka bentuk anda:

touch theme.tsx
  • Salin dan tampal konfigurasi tema lalai
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;

Pembekal Tema Pelaksana

Kemas kini apl/_layout.tsx anda:

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
// In components/Text.tsx

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

export const Text = createText<Theme>();

Jom gunakannya dalam skrin utama kami

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

Seperti yang anda lihat dalam kod di atas, kami menghantar margin sebagai "m" dan bukannya nombor. Kami mendapat nilai daripada theme.tsxfile kami.

// ./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
  },
});

Begini rupa paparan halaman utama kami

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

Komponen Pemuat Rangka

Mari bina kad Skeleton Loader

touch components/SkeletonLoader.tsx
// 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;

  • Kami mencipta kotak baharu sebagai komponen yang telah ditetapkan daripada pakej @shopify/restyle dan ini akan cara kami mencipta Kotak Rangka
const Box = createBox<Theme>();
  • Buat komponen CardSkeleton baharu menggunakan createStyleComponent untuk mencipta komponen tersuai dan kami lulus prop yang merupakan jarak dan cardVariants yang perlu kami tentukan dalam fail theme.tsx kami
type Props = SpacingProps<Theme> &
  VariantProps<Theme, "cardVariants"> &
  BackgroundColorProps<Theme> &
  React.ComponentProps<typeof View>;

const CardSkeleton = createRestyleComponent<Props, Theme>([
  spacing,
  createVariant({ themeKey: "cardVariants" }),
]);
  • Buat Komponen SkeletonLoader untuk menghasilkan komponen Kad Skelton kami
// 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>
  );
};

Kami mempunyai satu perkara lagi untuk menjadikannya berfungsi, kemas kini theme.tsxfile untuk mempunyai 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",
    },
  },
});

Itu bagus, tetapi mari kita animasikan kepada komponen kami

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

Dan inilah kod komponen penuh:

// 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,
    },
  },

Tambahkan konfigurasi tema gelap kami dalam reka letak apl kami dengan menambahkannya pada fail layout.tsx kami

npx create-expo-app@latest
  • Berdasarkan skema warna, gunakan tema cahaya lalai atau dalam mod gelap gunakan konfigurasi DarkTheme yang ditakrifkan dalam fail theme.tsx
 // app/_layout.tsx

 import tema, { darkTheme } daripada "@/theme";

 //... selebihnya kod

    <ThemeProvider theme={colorSchema === "gelap" ? darkTheme : theme}>
      <Timbunan>
        <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
        <Stack.Screen name=" not-found" />
      </Timbunan>
      <Bar Status>



<p>Ini dia mod gelap dan terang.</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 voila, kami berjaya mencipta komponen UI yang dikuatkuasakan jenis menggunakan pakej @shopify/restyle</p>

<p>Terima kasih :)</p>


          

            
        

Atas ialah kandungan terperinci Cara membina komponen UI yang dikuatkuasakan jenis dalam React Native menggunakan @shopify/restyle. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn