useState 在执行作为 props 传递的函数时导致速度变慢
useState causing slowness when executing function passed as props
我有一个 React 本机应用程序,其中有一个颜色配置、一种主题、一个特定的屏幕,我传递了一个像 props 这样的函数,它被执行并更新全局颜色,但是它会导致延迟大约一秒
这是我的应用程序
import { AppLoading } from 'expo';
import { Asset } from 'expo-asset';
import * as Font from 'expo-font';
import React, { useState, useEffect } from 'react';
import { Platform, StatusBar, StyleSheet, View, AsyncStorage } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import AppNavigator from './src/navigation/AppNavigator';
export default function App(props) {
const [isLoadingComplete, setLoadingComplete] = useState(false);
const [colors, setColor] = useState({});
// useEffect(() => {
// getColor();
// }, []);
const setDefaultColor = skin => {
const data = {
name: skin?.name,
primary: skin?.color?.primary,
secondary: skin?.color?.secondary,
complementary: skin?.color?.complementary,
};
setColor(data);
};
// async function getColor(skin) {
// const getColors = await AsyncStorage.getItem('colors');
// if (getColors) {
// const { color, name } = JSON.parse(getColors);
// } else {
// setColor({
// name: 'Preto',
// primary: '#000000',
// secondary: '#fff',
// complementary: '#000000',
// });
// }
// }
if (!isLoadingComplete && !props.skipLoadingScreen) {
return (
<AppLoading
startAsync={loadResourcesAsync}
onError={handleLoadingError}
onFinish={() => handleFinishLoading(setLoadingComplete)}
/>
);
}
return (
<View style={styles.container}>
{Platform.OS === 'ios' && <StatusBar barStyle="default" />}
<AppNavigator screenProps={{ colors, handleColor: setDefaultColor }} {...props} />
</View>
);
}
async function loadResourcesAsync() {
await Promise.all([
Asset.loadAsync([
require('./src/assets/images/robot-dev.png'),
require('./src/assets/images/robot-prod.png'),
]),
Font.loadAsync({
// This is the font that we are using for our tab bar
...Ionicons.font,
// We include SpaceMono because we use it in HomeScreen.js. Feel free to
// remove this if you are not using it in your app
Corbelb: require('./src/assets/fonts/corbelb.ttf'),
Corbel: require('./src/assets/fonts/corbel.ttf'),
}),
]);
}
function handleLoadingError(error) {
// In this case, you might want to report the error to your error reporting
// service, for example Sentry
console.warn(error);
}
function handleFinishLoading(setLoadingComplete) {
setLoadingComplete(true);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
});
这是我进行颜色配置的屏幕
import React from 'react';
import { View, Modal, AsyncStorage, StyleSheet, Text, TouchableOpacity } from 'react-native';
import Mdi from 'react-native-vector-icons/MaterialCommunityIcons';
export default function SettingsColors(props) {
const { modalVisible, closeModal, screenProps } = props;
const data = [
{
name: 'Azul',
color: {
primary: '#0061ab',
secondary: 'white',
complementary: '#01256f',
},
},
{
name: 'Vermelho',
color: {
primary: '#ab000d',
secondary: 'white',
complementary: '#7e000a',
},
},
{
name: 'Laranja',
color: {
primary: '#ff7200',
secondary: 'white',
complementary: '#ac4d00',
},
},
{
name: 'Preto',
color: {
primary: '#000000',
secondary: '#fff',
complementary: '#000000',
},
},
{
name: 'Roxo',
color: {
primary: '#670097',
secondary: 'white',
complementary: '#480069',
},
},
{
name: 'Verde',
color: {
primary: '#1f8f04',
secondary: 'white',
complementary: '#177700',
},
},
{
name: 'Rosa',
color: {
primary: '#e402b1',
secondary: 'white',
complementary: '#9b0078',
},
},
{
name: 'Branco',
color: {
primary: '#ffffff',
secondary: 'black',
complementary: 'white',
},
},
];
function handleChangeColor(skin) {
screenProps.handleColor(skin);
}
return (
<Modal
animationType="fade"
transparent
visible={modalVisible}
onRequestClose={() => closeModal()}
>
<View style={styles.container}>
<View style={styles.header}>
<Mdi style={{ padding: 5 }} name="palette" color="black" size={30} />
<Text style={{ fontSize: 20 }}>Skins</Text>
</View>
<View style={styles.containerButton}>
{data.map((item, index) => (
<TouchableOpacity
key={index}
style={[styles.button, { backgroundColor: item.color.primary }]}
onPress={() => handleChangeColor(item)}
>
<Text
style={[
styles.text,
{
color: `${item.color.primary === '#ffffff' ? 'black' : 'white'}`,
},
]}
>
{item.name}
</Text>
</TouchableOpacity>
))}
</View>
</View>
</Modal>
);
}
const styles = StyleSheet.create({
container: {
marginTop: 80,
elevation: 10,
padding: 20,
borderRadius: 20,
margin: 20,
backgroundColor: '#fff',
},
header: {
width: '100%',
flexDirection: 'row',
alignItems: 'center',
alignSelf: 'flex-start',
borderBottomWidth: 1,
marginBottom: 10,
},
containerButton: {
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'center',
justifyContent: 'center',
},
button: {
alignItems: 'center',
justifyContent: 'center',
height: 60,
minWidth: 80,
padding: 10,
marginVertical: 10,
margin: 5,
borderRadius: 10,
elevation: 5,
},
text: {
color: 'white',
fontWeight: 'bold',
},
});
任何帮助或对发生的事情的解释,我将不胜感激。
看起来每当您更新颜色时,都会从项目的根部开始重新渲染,这很可能是导致速度变慢的原因。
我建议对此类行为使用 React Contexts。您的主要上下文将公开活动颜色和设置颜色的方法,可以通过消费者访问这些颜色。 (文档页面上的一个示例实际上是将它用于主题化组件,因此希望这会有所帮助。)
我有一个 React 本机应用程序,其中有一个颜色配置、一种主题、一个特定的屏幕,我传递了一个像 props 这样的函数,它被执行并更新全局颜色,但是它会导致延迟大约一秒
这是我的应用程序
import { AppLoading } from 'expo';
import { Asset } from 'expo-asset';
import * as Font from 'expo-font';
import React, { useState, useEffect } from 'react';
import { Platform, StatusBar, StyleSheet, View, AsyncStorage } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import AppNavigator from './src/navigation/AppNavigator';
export default function App(props) {
const [isLoadingComplete, setLoadingComplete] = useState(false);
const [colors, setColor] = useState({});
// useEffect(() => {
// getColor();
// }, []);
const setDefaultColor = skin => {
const data = {
name: skin?.name,
primary: skin?.color?.primary,
secondary: skin?.color?.secondary,
complementary: skin?.color?.complementary,
};
setColor(data);
};
// async function getColor(skin) {
// const getColors = await AsyncStorage.getItem('colors');
// if (getColors) {
// const { color, name } = JSON.parse(getColors);
// } else {
// setColor({
// name: 'Preto',
// primary: '#000000',
// secondary: '#fff',
// complementary: '#000000',
// });
// }
// }
if (!isLoadingComplete && !props.skipLoadingScreen) {
return (
<AppLoading
startAsync={loadResourcesAsync}
onError={handleLoadingError}
onFinish={() => handleFinishLoading(setLoadingComplete)}
/>
);
}
return (
<View style={styles.container}>
{Platform.OS === 'ios' && <StatusBar barStyle="default" />}
<AppNavigator screenProps={{ colors, handleColor: setDefaultColor }} {...props} />
</View>
);
}
async function loadResourcesAsync() {
await Promise.all([
Asset.loadAsync([
require('./src/assets/images/robot-dev.png'),
require('./src/assets/images/robot-prod.png'),
]),
Font.loadAsync({
// This is the font that we are using for our tab bar
...Ionicons.font,
// We include SpaceMono because we use it in HomeScreen.js. Feel free to
// remove this if you are not using it in your app
Corbelb: require('./src/assets/fonts/corbelb.ttf'),
Corbel: require('./src/assets/fonts/corbel.ttf'),
}),
]);
}
function handleLoadingError(error) {
// In this case, you might want to report the error to your error reporting
// service, for example Sentry
console.warn(error);
}
function handleFinishLoading(setLoadingComplete) {
setLoadingComplete(true);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
});
这是我进行颜色配置的屏幕
import React from 'react';
import { View, Modal, AsyncStorage, StyleSheet, Text, TouchableOpacity } from 'react-native';
import Mdi from 'react-native-vector-icons/MaterialCommunityIcons';
export default function SettingsColors(props) {
const { modalVisible, closeModal, screenProps } = props;
const data = [
{
name: 'Azul',
color: {
primary: '#0061ab',
secondary: 'white',
complementary: '#01256f',
},
},
{
name: 'Vermelho',
color: {
primary: '#ab000d',
secondary: 'white',
complementary: '#7e000a',
},
},
{
name: 'Laranja',
color: {
primary: '#ff7200',
secondary: 'white',
complementary: '#ac4d00',
},
},
{
name: 'Preto',
color: {
primary: '#000000',
secondary: '#fff',
complementary: '#000000',
},
},
{
name: 'Roxo',
color: {
primary: '#670097',
secondary: 'white',
complementary: '#480069',
},
},
{
name: 'Verde',
color: {
primary: '#1f8f04',
secondary: 'white',
complementary: '#177700',
},
},
{
name: 'Rosa',
color: {
primary: '#e402b1',
secondary: 'white',
complementary: '#9b0078',
},
},
{
name: 'Branco',
color: {
primary: '#ffffff',
secondary: 'black',
complementary: 'white',
},
},
];
function handleChangeColor(skin) {
screenProps.handleColor(skin);
}
return (
<Modal
animationType="fade"
transparent
visible={modalVisible}
onRequestClose={() => closeModal()}
>
<View style={styles.container}>
<View style={styles.header}>
<Mdi style={{ padding: 5 }} name="palette" color="black" size={30} />
<Text style={{ fontSize: 20 }}>Skins</Text>
</View>
<View style={styles.containerButton}>
{data.map((item, index) => (
<TouchableOpacity
key={index}
style={[styles.button, { backgroundColor: item.color.primary }]}
onPress={() => handleChangeColor(item)}
>
<Text
style={[
styles.text,
{
color: `${item.color.primary === '#ffffff' ? 'black' : 'white'}`,
},
]}
>
{item.name}
</Text>
</TouchableOpacity>
))}
</View>
</View>
</Modal>
);
}
const styles = StyleSheet.create({
container: {
marginTop: 80,
elevation: 10,
padding: 20,
borderRadius: 20,
margin: 20,
backgroundColor: '#fff',
},
header: {
width: '100%',
flexDirection: 'row',
alignItems: 'center',
alignSelf: 'flex-start',
borderBottomWidth: 1,
marginBottom: 10,
},
containerButton: {
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'center',
justifyContent: 'center',
},
button: {
alignItems: 'center',
justifyContent: 'center',
height: 60,
minWidth: 80,
padding: 10,
marginVertical: 10,
margin: 5,
borderRadius: 10,
elevation: 5,
},
text: {
color: 'white',
fontWeight: 'bold',
},
});
任何帮助或对发生的事情的解释,我将不胜感激。
看起来每当您更新颜色时,都会从项目的根部开始重新渲染,这很可能是导致速度变慢的原因。
我建议对此类行为使用 React Contexts。您的主要上下文将公开活动颜色和设置颜色的方法,可以通过消费者访问这些颜色。 (文档页面上的一个示例实际上是将它用于主题化组件,因此希望这会有所帮助。)