React Native 从主组件外部渲染useEffect()

jmo0nnb3  于 2022-11-17  发布在  React
关注(0)|答案(1)|浏览(142)

我已经设置了一个系统,如果你点击一次按钮,你会得到一个成就(奖牌)。处理计数器是否被按下一次的逻辑在奖牌屏幕文件中。因此,我必须先打开并渲染奖牌屏幕,然后点击按钮,以获得任何效果。
我如何使它的效果发生,而不管奖牌屏幕被渲染?默认屏幕是计数器屏幕。下面是代码:
计数器

import React, { useEffect, useState, useContext } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { useTheme } from '@react-navigation/native';

import { CountContext } from '../../contexts/CountContext';
import { styles } from "../../styles/Styles";

const CounterScreen = () => {

    const { colors } = useTheme();
    const { setCounter, counter } = useContext(CountContext);

    return (
        <View style={styles.container}>
            <View>
                <TouchableOpacity
                    onPress={() => setCounter(counter + 1)}
                    style={[styles.counterButton, {backgroundColor: colors.primary}]}>
                    <Text style={styles.counterText}>{counter}</Text>
                </TouchableOpacity>
            </View>
        </View>
        
    );
}

export default CounterScreen;

奖牌

import React, { useEffect, useState, useContext } from 'react';
import { View, Text, ScrollView } from 'react-native';
import { useTheme } from '@react-navigation/native';
import Ionicons from 'react-native-vector-icons/Ionicons';

import { CountContext } from '../../contexts/CountContext';
import { BadgeContext } from '../../contexts/BadgeContext';
import { styles } from "../../styles/Styles";

export default function MedalsScreen({ navigation }) {

    const { colors } = useTheme();
    const { counter } = useContext(CountContext);
    const { badgeCount, setBadgeCount } = useContext(BadgeContext);
    
    const [achieved, setAchieved] = useState(false);
    const [customizeAchieved1, setCustomizeAchieved1] = useState(false);

    const [countMedal1, setCountMedal1] = useState(0.25);
    const [countMedal2, setCountMedal2] = useState(0.25);
    const [countMedal3, setCountMedal3] = useState(0.25);
    const [countMedal4, setCountMedal4] = useState(0.25);
    const [countMedal5, setCountMedal5] = useState(0.25);
    const [countMedal6, setCountMedal6] = useState(0.25);
    const [customizeMedal1, setCustomizeMedal1] = useState(0.25);
    const [customizeMedal2, setCustomizeMedal2] = useState(0.25);
    const [secretMedal, setSecretMedal] = useState(0.25); // 

    useEffect(() => {

        if (counter != 1 && counter != 100 && counter != 1000 && counter != 10000 && counter != 100000 && counter != 1000000) {
            setAchieved(false);
        }
        
        if (counter == 1 && achieved == false) {
            setCountMedal1(1);
            setBadgeCount(badgeCount + 1)
            setAchieved(true);
        }

        if (counter == 100 && achieved == false) {
            setCountMedal2(1);
            setBadgeCount(badgeCount + 1)
            setAchieved(true);
        }

        if (counter == 1000 && achieved == false) {
            setCountMedal3(1);
            setBadgeCount(badgeCount + 1)
            setAchieved(true);
        }

        if (counter == 10000 && achieved == false) {
            setCountMedal4(1);
            setBadgeCount(badgeCount + 1)
            setAchieved(true);
        }

        if (counter == 100000 && achieved == false) {
            setCountMedal5(1);
            setBadgeCount(badgeCount + 1)
            setAchieved(true);
        }

        if (counter == 1000000 && achieved == false) {
            setCountMedal6(1);
            setBadgeCount(badgeCount + 1)
            setAchieved(true);
        }

        if (colors.primary != '#FFBF00' && customizeAchieved1 == false) {
            setCustomizeMedal1(1);
            setBadgeCount(badgeCount + 1)
            setCustomizeAchieved1(true);
        }
        
    })

    return (
        <ScrollView style={{ backgroundColor: '#181818' }}>

            <View style={styles.medalCardContainer}>

                <View style={[styles.medalCard, { borderColor: colors.border, opacity: countMedal1 }]}>
                    <Ionicons name='radio-button-on-outline' size={50} color={colors.primary} />
                    <View>
                        <Text style={styles.medalCardTitle}>Getting Started</Text>
                        <Text style={styles.medalCardSubTitle}>Tap the button for the first time</Text>
                    </View>
                </View>

                <View style={[styles.medalCard, { borderColor: colors.border, opacity: countMedal2 }]}>
                    <Ionicons name='radio-button-on-outline' size={50} color={colors.primary} />
                    <View>
                        <Text style={styles.medalCardTitle}>Placeholder | Tap 2</Text>
                        <Text style={styles.medalCardSubTitle}>Tap the button 100 times</Text>
                    </View>
                </View>

                <View style={[styles.medalCard, { borderColor: colors.border, opacity: countMedal3 }]}>
                    <Ionicons name='radio-button-on-outline' size={50} color={colors.primary} />
                    <View style={styles.medalTextContainer}>
                        <Text style={styles.medalCardTitle}>Placeholder | Tap 3</Text>
                        <Text style={styles.medalCardSubTitle}>Tap the button 1000 times</Text>
                    </View>
                </View>

                <View style={[styles.medalCard, { borderColor: colors.border, opacity: countMedal4 }]}>
                    <Ionicons name='radio-button-on-outline' size={50} color={colors.primary} />
                    <View>
                        <Text style={styles.medalCardTitle}>Placeholder | Tap 4</Text>
                        <Text style={styles.medalCardSubTitle}>Tap the button 10000 times</Text>
                    </View>
                </View>

                <View style={[styles.medalCard, { borderColor: colors.border, opacity: countMedal5 }]}>
                    <Ionicons name='radio-button-on-outline' size={50} color={colors.primary} />
                    <View>
                        <Text style={styles.medalCardTitle}>Placeholder | Tap 5</Text>
                        <Text style={styles.medalCardSubTitle}>Tap the button 100000 times</Text>
                    </View>
                </View>

                <View style={[styles.medalCard, { borderColor: colors.border, opacity: countMedal6 }]}>
                    <Ionicons name='radio-button-on-outline' size={50} color={colors.primary} />
                    <View>
                        <Text style={styles.medalCardTitle}>Placeholder | Tap 6</Text>
                        <Text style={styles.medalCardSubTitle}>Tap the button 1000000 times</Text>
                    </View>
                </View>

                <View style={[styles.medalCard, { borderColor: colors.border, opacity: customizeMedal1 }]}>
                    <Ionicons name='color-palette' size={50} color={colors.primary} />
                    <View>
                        <Text style={styles.medalCardTitle}>Pablo Picasso</Text>
                        <Text style={styles.medalCardSubTitle}>Change the theme for the first time</Text>
                    </View>
                </View>

                <View style={[styles.medalCard, { borderColor: colors.border, opacity: customizeMedal2 }]}>
                    <Ionicons name='color-wand' size={50} color={colors.primary} />
                    <View>
                        <Text style={styles.medalCardTitle}>Placeholder | Customize 2</Text>
                        <Text style={styles.medalCardSubTitle}>Select an effect for the first time</Text>
                    </View>
                </View>

                <View style={[styles.medalCard, { borderColor: colors.border, opacity: secretMedal }]}>
                    <Ionicons name='help' size={50} color={colors.primary} />
                    <View>
                        <Text style={styles.medalCardTitle}>Placeholder | Secret 1</Text>
                        <Text style={styles.medalCardSubTitle}>Maybe it's in the source code?</Text>
                    </View>
                </View>

            </View>

        </ScrollView>
    );
}

主菜单

import React, { useState, useMemo } from 'react';
import Ionicons from 'react-native-vector-icons/Ionicons';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import * as NavigationBar from "expo-navigation-bar";
import { StatusBar } from 'expo-status-bar';

import CounterScreen from './screens/CounterScreen';
import CustomizeScreen from './screens/CustomizeScreen';
import SettingsScreen from './screens/SettingsScreen';
import MedalsScreen from './screens/MedalsScreen';

import { Amber, Tiger, Crimson, Blush, Amethyst, Azure, Lime } from "../styles/Themes"
import { ThemeContext } from '../contexts/ThemeContext';
import { CountContext } from '../contexts/CountContext';
import { BadgeContext } from '../contexts/BadgeContext';

// IMPORTS // IMPORTS // IMPORTS // IMPORTS // IMPORTS // IMPORTS // IMPORTS // IMPORTS // IMPORTS 

const counterName = 'Counter';
const customizeName = 'Customize';
const settingsName = 'Settings';
const medalsName = "Medals";

const Tab = createBottomTabNavigator();
NavigationBar.setBackgroundColorAsync("#212121");

// DECLARATIONS // DECLARATIONS // DECLARATIONS // DECLARATIONS // DECLARATIONS // DECLARATIONS 

export default function MainContainer() {

    const [theme, setTheme] = useState('Amber');
    const [counter, setCounter] = useState(0);
    const [badgeCount, setBadgeCount] = useState(0);

    const containerTheme = useMemo(() => {
        switch (theme) {
            case 'Amber':
                return Amber;
            case 'Tiger':
                return Tiger;
            case 'Crimson':
                return Crimson;
            case 'Blush':
                return Blush;
            case 'Amethyst':
                return Amethyst;
            case 'Azure':
                return Azure;
            case 'Lime':
                return Lime;
            default: console.log("Invalid theme (" + theme + ")");
        }
    }, [theme])

    return (

        <ThemeContext.Provider value={{ theme, setTheme }}>
            <BadgeContext.Provider value={{ badgeCount, setBadgeCount }}>
                <CountContext.Provider value={{ counter, setCounter }}>
                    <NavigationContainer theme={containerTheme}>

                        <StatusBar style="auto" />

                        <Tab.Navigator
                            initialRouteName={counterName}
                            screenOptions={({ route }) => ({
                                tabBarIcon: ({ focused, color, size }) => {
                                    let iconName;
                                    let rn = route.name;

                                    if (rn === counterName) {
                                        iconName = focused ? 'radio-button-on-outline' : 'radio-button-off-outline';
                                    } else if (rn === customizeName) {
                                        iconName = focused ? 'color-palette' : 'color-palette-outline';
                                    } else if (rn === medalsName) {
                                        iconName = focused ? 'medal' : 'medal-outline';
                                    } else if (rn === settingsName) {
                                        iconName = focused ? 'settings' : 'settings-outline';
                                    }

                                    return <Ionicons name={iconName} size={size} color={color} />

                                },
                                tabBarInactiveTintColor: '#aaaaaa',
                                tabBarLabelStyle: { paddingBottom: 10, fontSize: 10 },
                                tabBarStyle: { padding: 10, height: 70, borderTopWidth: 1 },

                                headerStyle: { borderBottomWidth: 1 },
                                headerTitleAlign: 'center',
                                headerTitleStyle: { fontSize: 20 },
                            })}>

                            <Tab.Screen name={counterName} component={CounterScreen} />
                            <Tab.Screen name={customizeName} component={CustomizeScreen} />
                            <Tab.Screen name={medalsName} component={MedalsScreen} 
                            options={{ tabBarBadge: badgeCount ? badgeCount : undefined }}
                            listeners={{
                                tabPress: e => {
                                    setBadgeCount(0);
                                }
                            }}
                              />
                            <Tab.Screen name={settingsName} component={SettingsScreen} />

                        </Tab.Navigator>

                    </NavigationContainer>
                </CountContext.Provider>
            </BadgeContext.Provider>
        </ThemeContext.Provider>

    );
}
bmp9r5qi

bmp9r5qi1#

效果绑定到呈现生命周期。在不呈现组件的情况下无法运行效果。如果要运行效果,请将函数上移一级。

相关问题