useState вызывает медлительность при выполнении функции, переданной как реквизит - PullRequest
0 голосов
/ 02 февраля 2020

У меня есть нативное приложение, в котором у меня есть цветовая конфигурация, своего рода темы, у меня есть определенный экран c, и я передаю функцию наподобие реквизита, которая выполняется и обновляет глобальные цвета, однако это вызывает задержка примерно в одну секунду

это мое приложение

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

любая помощь или объяснение того, что происходит, я буду благодарен.

1 Ответ

1 голос
/ 03 февраля 2020

Похоже, что когда вы обновляете цвета, это вызывает повторное рендеринг из самого root вашего проекта, что, скорее всего, вызывает замедление.

Я бы предложил использовать Реагировать Контексты для этого типа поведения. Ваш основной контекст будет отображать активные цвета и метод для установки цветов, которые могут быть доступны через потребителя. (Один из примеров на странице документации на самом деле использует его для тематических компонентов, так что, надеюсь, это поможет.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...