从主组件外部渲染useEffect()



我设置了一个系统,如果你点击一个按钮,你就会获得一个成就(奖章)。处理计数器是否被按过一次的逻辑在medal屏幕文件中。因此,我必须首先打开并渲染奖牌屏幕,然后单击按钮以产生任何效果。

我如何使它的效果会发生,而不管奖牌屏幕被渲染?默认界面为Counter界面。下面是代码:

柜台

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

效果绑定到渲染生命周期。不呈现组件就不能运行效果。如果您想运行它,请将该函数向上移动一个级别。

最新更新