英文:
React Native switch component's state resets after re-entering screen
问题
以下是代码的翻译部分:
在React Native中,我正在使用开关组件来在浅色模式和深色模式之间切换,使用了状态、上下文和事件监听器,但是在重新进入屏幕后,开关的状态会重置,表现出一种我在其他地方没有看到的奇怪行为。
这是包含开关的文件:
import React, { useState, useContext } from 'react';
import { Text, TouchableOpacity, SafeAreaView, Switch } from 'react-native';
import { useNavigation } from '@react-navigation/core';
import theme from '../assets/styles/theme';
import ThemeContext from '../context/ThemeContext';
import { StatusBar } from 'expo-status-bar';
import { EventRegister } from 'react-native-event-listeners';
const Settings = () => {
const navigation = useNavigation();
const colors: any = useContext(ThemeContext);
const [mode, setMode] = useState(false);
return (
<SafeAreaView
style={[theme.container, { backgroundColor: colors.background }]}
>
<Switch
onValueChange={(value) => {
setMode((value) => !value);
EventRegister.emit('changeTheme', value);
}}
value={mode}
/>
<TouchableOpacity
onPress={() => navigation.navigate('Home')}
style={[theme.button, { backgroundColor: colors.button }]}
>
<Text style={[theme.buttonText, { color: colors.buttonText }]}>
返回
</Text>
</TouchableOpacity>
<StatusBar style={mode === false ? 'dark' : 'light'}></StatusBar>
</SafeAreaView>
);
};
export default Settings;
以及包含事件监听器的App.tsx:
import React, { useState, useEffect } from 'react';
import { NavigationContainer } from '@react-navigation/native';
import AppNavigator from './navigation/AppNavigator';
import { EventRegister } from 'react-native-event-listeners';
import ThemeContext from './context/ThemeContext';
import colors from './assets/colors/colors';
export default function App() {
const [mode, setMode] = useState(false);
useEffect(() => {
let eventListener: string = EventRegister.addEventListener(
'changeTheme',
(data) => {
setMode(data);
}
);
return () => {
EventRegister.removeEventListener(eventListener);
};
});
return (
<ThemeContext.Provider value={mode === true ? colors.dark : colors.light}>
<NavigationContainer>
<AppNavigator />
</NavigationContainer>
</ThemeContext.Provider>
);
}
这就是奇怪的行为:链接
我还是相对新手,正在学习React,所以感谢任何帮助。
编辑:根据user18309290的建议,我成功实施了一个解决方法。
import React, { useState, useContext } from 'react';
import { Text, TouchableOpacity, SafeAreaView, Switch } from 'react-native';
import { useNavigation } from '@react-navigation/core';
import theme from '../assets/styles/theme';
import ThemeContext from '../context/ThemeContext';
import { StatusBar } from 'expo-status-bar';
import { EventRegister } from 'react-native-event-listeners';
import colors from '../assets/colors/colors';
const Settings = () => {
const navigation = useNavigation();
const scheme: any = useContext(ThemeContext);
let aux = scheme;
aux === colors.dark ? (aux = true) : (aux = false);
const [mode, setMode] = useState(aux);
return (
<SafeAreaView
style={[theme.container, { backgroundColor: scheme.background }]
>
<Switch
onValueChange={(value) => {
setMode((value) => !value);
EventRegister.emit('changeTheme', value);
}}
value={aux}
/>
<TouchableOpacity
onPress={() => navigation.navigate('Home')}
style={[theme.button, { backgroundColor: scheme.button }]
}>
<Text style={[theme.buttonText, { color: scheme.buttonText }]}>
返回
</Text>
</TouchableOpacity>
<StatusBar style={mode === false ? 'dark' : 'light'}></StatusBar>
</SafeAreaView>
);
};
export default Settings;
虽然我对它不太满意,将来可能会重新设计它,但它解决了问题,现在开关可以正常工作,如果有人遇到我曾经遇到的相同问题,这可能会有所帮助。
英文:
I'm using React Native's switch component to toggle between Light and Dark modes, using States, Context and Event Listeners and the switch's state is resetting after re-entering the screen where it is at with a weird behavior I haven't seen anywhere online.
This is the file where the switch is at:
import React, { useState, useContext } from 'react';
import { Text, TouchableOpacity, SafeAreaView, Switch } from 'react-native';
import { useNavigation } from '@react-navigation/core';
import theme from '../assets/styles/theme';
import ThemeContext from '../context/ThemeContext';
import { StatusBar } from 'expo-status-bar';
import { EventRegister } from 'react-native-event-listeners';
const Settings = () => {
const navigation = useNavigation();
const colors: any = useContext(ThemeContext);
const [mode, setMode] = useState(false);
return (
<SafeAreaView
style={[theme.container, { backgroundColor: colors.background }]}
>
<Switch
onValueChange={(value) => {
setMode((value) => !value);
EventRegister.emit('changeTheme', value);
}}
value={mode}
/>
<TouchableOpacity
onPress={() => navigation.navigate('Home')}
style={[theme.button, { backgroundColor: colors.button }]}
>
<Text style={[theme.buttonText, { color: colors.buttonText }]}>
Back
</Text>
</TouchableOpacity>
<StatusBar style={mode === false ? 'dark' : 'light'}></StatusBar>
</SafeAreaView>
);
};
export default Settings;
And this App.tsx where the Event Listener is:
import React, { useState, useEffect } from 'react';
import { NavigationContainer } from '@react-navigation/native';
import AppNavigator from './navigation/AppNavigator';
import { EventRegister } from 'react-native-event-listeners';
import ThemeContext from './context/ThemeContext';
import colors from './assets/colors/colors';
export default function App() {
const [mode, setMode] = useState(false);
useEffect(() => {
let eventListener: string = EventRegister.addEventListener(
'changeTheme',
(data) => {
setMode(data);
}
);
return () => {
EventRegister.removeEventListener(eventListener);
};
});
return (
<ThemeContext.Provider value={mode === true ? colors.dark : colors.light}>
<NavigationContainer>
<AppNavigator />
</NavigationContainer>
</ThemeContext.Provider>
);
}
And this is the weird behavior:
I am still pretty new and learning React so any help is appreciated, thanks.
EDIT:
After the suggestion from user18309290 I managed to do a workaround that works.
import React, { useState, useContext } from 'react';
import { Text, TouchableOpacity, SafeAreaView, Switch } from 'react-native';
import { useNavigation } from '@react-navigation/core';
import theme from '../assets/styles/theme';
import ThemeContext from '../context/ThemeContext';
import { StatusBar } from 'expo-status-bar';
import { EventRegister } from 'react-native-event-listeners';
import colors from '../assets/colors/colors';
const Settings = () => {
const navigation = useNavigation();
const scheme: any = useContext(ThemeContext);
let aux = scheme;
aux === colors.dark ? (aux = true) : (aux = false);
const [mode, setMode] = useState(aux);
return (
<SafeAreaView
style={[theme.container, { backgroundColor: scheme.background }]}
>
<Switch
onValueChange={(value) => {
setMode((value) => !value);
EventRegister.emit('changeTheme', value);
}}
value={aux}
/>
<TouchableOpacity
onPress={() => navigation.navigate('Home')}
style={[theme.button, { backgroundColor: scheme.button }]}
>
<Text style={[theme.buttonText, { color: scheme.buttonText }]}>
Back
</Text>
</TouchableOpacity>
<StatusBar style={mode === false ? 'dark' : 'light'}></StatusBar>
</SafeAreaView>
);
};
export default Settings;
While I'm not exactly happy with it and will probably rework it later, it does solve the issue and the switch now works properly, in case someone has the same problem I had.
答案1
得分: 0
useState
只是向组件(比如 Settings
)添加一个状态变量。当组件挂载时,变量被设置为默认值,比如 false
。
使用 context
来设置默认值,类似这样:
const colors: any = useContext(ThemeContext);
const [mode, setMode] = useState(colors.mode);
或者完全删除本地状态。
英文:
useState
just adds a state variable to a component like Settings
. When a component mounts a variable is set to default like false
.
Use context
to set the default value. Something like this:
const colors: any = useContext(ThemeContext);
const [mode, setMode] = useState(colors.mode);
Or remove the local state all together.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论