React Native开关组件在重新进入屏幕后状态重置。

huangapple go评论51阅读模式
英文:

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 &#39;react&#39;;
import { Text, TouchableOpacity, SafeAreaView, Switch } from &#39;react-native&#39;;
import { useNavigation } from &#39;@react-navigation/core&#39;;
import theme from &#39;../assets/styles/theme&#39;;
import ThemeContext from &#39;../context/ThemeContext&#39;;
import { StatusBar } from &#39;expo-status-bar&#39;;
import { EventRegister } from &#39;react-native-event-listeners&#39;;
const Settings = () =&gt; {
const navigation = useNavigation();
const colors: any = useContext(ThemeContext);
const [mode, setMode] = useState(false);
return (
&lt;SafeAreaView
style={[theme.container, { backgroundColor: colors.background }]}
&gt;
&lt;Switch
onValueChange={(value) =&gt; {
setMode((value) =&gt; !value);
EventRegister.emit(&#39;changeTheme&#39;, value);
}}
value={mode}
/&gt;
&lt;TouchableOpacity
onPress={() =&gt; navigation.navigate(&#39;Home&#39;)}
style={[theme.button, { backgroundColor: colors.button }]}
&gt;
&lt;Text style={[theme.buttonText, { color: colors.buttonText }]}&gt;
Back
&lt;/Text&gt;
&lt;/TouchableOpacity&gt;
&lt;StatusBar style={mode === false ? &#39;dark&#39; : &#39;light&#39;}&gt;&lt;/StatusBar&gt;
&lt;/SafeAreaView&gt;
);
};
export default Settings;

And this App.tsx where the Event Listener is:

import React, { useState, useEffect } from &#39;react&#39;;
import { NavigationContainer } from &#39;@react-navigation/native&#39;;
import AppNavigator from &#39;./navigation/AppNavigator&#39;;
import { EventRegister } from &#39;react-native-event-listeners&#39;;
import ThemeContext from &#39;./context/ThemeContext&#39;;
import colors from &#39;./assets/colors/colors&#39;;
export default function App() {
const [mode, setMode] = useState(false);
useEffect(() =&gt; {
let eventListener: string = EventRegister.addEventListener(
&#39;changeTheme&#39;,
(data) =&gt; {
setMode(data);
}
);
return () =&gt; {
EventRegister.removeEventListener(eventListener);
};
});
return (
&lt;ThemeContext.Provider value={mode === true ? colors.dark : colors.light}&gt;
&lt;NavigationContainer&gt;
&lt;AppNavigator /&gt;
&lt;/NavigationContainer&gt;
&lt;/ThemeContext.Provider&gt;
);
}

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 &#39;react&#39;;
import { Text, TouchableOpacity, SafeAreaView, Switch } from &#39;react-native&#39;;
import { useNavigation } from &#39;@react-navigation/core&#39;;
import theme from &#39;../assets/styles/theme&#39;;
import ThemeContext from &#39;../context/ThemeContext&#39;;
import { StatusBar } from &#39;expo-status-bar&#39;;
import { EventRegister } from &#39;react-native-event-listeners&#39;;
import colors from &#39;../assets/colors/colors&#39;;
const Settings = () =&gt; {
const navigation = useNavigation();
const scheme: any = useContext(ThemeContext);
let aux = scheme;
aux === colors.dark ? (aux = true) : (aux = false);
const [mode, setMode] = useState(aux);
return (
&lt;SafeAreaView
style={[theme.container, { backgroundColor: scheme.background }]}
&gt;
&lt;Switch
onValueChange={(value) =&gt; {
setMode((value) =&gt; !value);
EventRegister.emit(&#39;changeTheme&#39;, value);
}}
value={aux}
/&gt;
&lt;TouchableOpacity
onPress={() =&gt; navigation.navigate(&#39;Home&#39;)}
style={[theme.button, { backgroundColor: scheme.button }]}
&gt;
&lt;Text style={[theme.buttonText, { color: scheme.buttonText }]}&gt;
Back
&lt;/Text&gt;
&lt;/TouchableOpacity&gt;
&lt;StatusBar style={mode === false ? &#39;dark&#39; : &#39;light&#39;}&gt;&lt;/StatusBar&gt;
&lt;/SafeAreaView&gt;
);
};
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.

huangapple
  • 本文由 发表于 2023年3月4日 07:18:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/75632633.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定