admin管理员组

文章数量:1292346

I have tried utilizing Zustand for state management for React Native, and here's what happened:

  1. When I use the web version of my app and tried navigating into the page for promo details (which is accessed through [id].tsx file) directly using its respective URL (example is localhost:3000/promos/1), it doesn't display anything.

  2. However, when navigating from the home page to a respective page, it displays data from its assign JSON object.

  3. Using sessionStorage and URLSearchParams is out of the window since the application was built not just for web, but also for mobile devices.

//promos.tsx

import Container from "@/components/Container";
import { promos } from "@/data/home";
import { PromoType, usePromoStore } from "@/store/home/usePromo";
import { useRouter } from "expo-router";
import { FlatList, Image, TouchableOpacity } from "react-native";
import { Card, Text } from "react-native-paper";
import Animated from "react-native-reanimated";
import styled from "styled-components/native";

interface PromoCardType {
    promo: PromoType;
    onOpen: () => void;
}

const StyledCard = styled(Card)({
    width: 350,
    borderRadius: 12,
    overflow: "hidden",
    backgroundColor: "white",
    marginTop: 10,
    marginBottom: 10,
})

const StyledImage = styled(Image)({
    width: "100%",
    height: 200,
    borderBottomLeftRadius:0,
    borderBottomRightRadius: 0
})

const StyledButton = styled(TouchableOpacity)({
    marginTop:10,
    backgroundColor: "#0265A1",
    width: 100,
    height: 30,
    borderRadius: 8,
    justifyContent: "center", 
})

const PromoCard = ({ promo, onOpen, }: PromoCardType) => {
    return(
        <StyledCard>
            <StyledImage source={promo.promoImage} />
            <Card.Content
                style={{
                    alignItems: "center"
                }}>
                <Text style={{ 
                    fontWeight: "bold", 
                    textAlign: "center", 
                    color: "#333", 
                    fontSize: 15, 
                    marginTop: 20, 
                }}>
                    {promo.promoHeader}
                </Text>
                <StyledButton onPress={onOpen}>
                    <Text style={{ 
                        color: "white", 
                        fontSize: 12,
                        textAlign: "center",
                        fontWeight: "light",
                    }}>
                        Read more
                    </Text>
                </StyledButton>
            </Card.Content>
        </StyledCard>
    )
}

const Promos = () => {
    const router = useRouter();

    const setSelectedPromo = usePromoStore(
        (state) => state.setSelectedPromo
    );

    const handlePromoNav = (promoId: number, data: PromoType) => {
        setSelectedPromo(data);

        router.push({
            pathname: "/promos/[id]",
            params: { id: promoId },
        });
    }

    return (
        <Container>
            <Animated.View style={{ alignItems:"center" }}>
                <FlatList
                    data={promos}
                    showsVerticalScrollIndicator={false}
                    renderItem={({item}) => (
                        <PromoCard
                            key={item.promoId}
                            promo={item}
                            onOpen={() => handlePromoNav(item.promoId, item)} />  
                        )}
                />
            </Animated.View>
        </Container>
    );
}
 
export default Promos;
//[id].tsx
import { usePromoStore } from "@/store/home/usePromo";
import { Stack } from "expo-router";

import Animated from "react-native-reanimated";

import { Text } from "react-native-paper";

import { Dimensions, Image, Platform, View } from "react-native";

import styled from "styled-components/native";
import Container from "@/components/Container";

const { width } = Dimensions.get("window")

const StyledText = styled(Text)({
    fontWeight: "bold",
    textAlign: "center",
    color: "#333",
    fontSize: 15,
    marginTop: 20,
    marginBottom: 10
})

const ImageHeader = styled(Image)({
    width: Math.min(500, width),
    height: Math.min(203, (203/500) * width),
})

const ImageDetail = styled(Image)({
    width: Math.min(500, width),
    height: Math.min(650, (1000 /667) * (width * 0.935)),
})

export default function GetPromo() {
    const selectedPromo = usePromoStore(
        (state) => state.selectedPromo
    );

    return (
        <Container>
            <Stack.Screen
                name="promos/[id]"
                options={{
                    headerTitle:"",
                    headerShown: true,
                    headerBackVisible: Platform.OS === 'android'
                }} />
            <Animated.ScrollView
                scrollEventThrottle={16}
                contentContainerStyle={{ 
                    backgroundColor: "white",
                    alignContent: "center",
                }}
                showsVerticalScrollIndicator={false}
                >
                {selectedPromo
                && (
                    <View style={{ alignItems: "center", }}>
                        <ImageHeader source={selectedPromo.promoContent.promoImageFull} />
                        <View style={{ alignItems: "center", paddingBottom: 15, }}>
                            <StyledText>
                                {selectedPromo.promoContent.promoTitle}
                            </StyledText>
                            <Text
                                style={{
                                marginTop: 15,
                                marginLeft: 10,
                                marginRight: 10,
                                paddingHorizontal: 15,
                                textAlign: "left"
                            }}>
                                {selectedPromo.promoContent.promoDesc}
                            </Text>
                            <StyledText>
                                {selectedPromo.promoContent.promoDetail}
                            </StyledText>
                            {selectedPromo.promoContent.promoDetailImage && 
                                <ImageDetail source={selectedPromo.promoContent.promoDetailImage} resizeMode="contain" />
                            }
                        </View>
                    </View>
                )}
            </Animated.ScrollView>
        </Container>
    )
}
//usePromo.ts
import { create } from "zustand";

export interface PromoType {
    promoImage: string,
    promoHeader: string,
    promoContent: PromoContentType
}

export interface PromoContentType {
    promoImageFull: string,
    promoTitle: string,
    promoDesc: string,
    promoDetail: string,
    promoDetailImage: string,
}

interface PromoStore {
    selectedPromo: PromoType | null;
    setSelectedPromo: (selectedPromo: PromoType | null) => void;
}

export const usePromoStore = create<PromoStore>((set) => ({
    selectedPromo: null,
    setSelectedPromo: (promo) =>
        set( { selectedPromo: promo })
}))

What changes should I make in my code for this to work seamlessly?

Initially, I have tried refactoring my Zustand store code, yet it is still not working in both web and mobile. I would like to useAsyncStorage, yet I have read that it may cause slow load times.

本文标签: react nativeHow do I make the attached code for Zustand work for persistent dataStack Overflow