Изменен от реакции собственного класса на функцию, и он не работает на 100%

Я пытаюсь превратить класс в функцию. Это в основном потому, что если я смогу заставить его работать, я хочу использовать его для изучения различных анимаций, у меня был некоторый успех, но не на 100%. Первоначально он отображал значок, который при нажатии вращался в одну сторону, а при повторном нажатии - в другую. Что я пытался сделать, так это избавиться от значка и заменить его изображением. Он работает при нажатии один раз, но затем ничего не делает.

Я борюсь с переключаемым аспектом этого и устанавливаю состояние, которое я думаю, потому что я не могу правильно настроить его в функции.

Я пробовал несколько вещей, но это лучшее, что я могу получить. Если я покажу исходный код, а затем то, что мне удалось изменить, возможно, кто-то сможет указать мне правильное направление относительно того, что я делаю неправильно.

Все, что я хочу, это изображение, которое отображается, а затем при нажатии вращается вправо, а затем, если щелкнуть снова, оно вращается влево.

Я делаю это, чтобы повозиться с настройками и, надеюсь, немного лучше изучить анимацию.

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

Оригинальный код:

import React from 'react';
import { View, StyleSheet, Animated, Image, TouchableOpacity } from 'react-native';
import { Ionicons } from '@expo/vector-icons';

const TabIcon = ({
  onPress,
  menuToggled
}) => {
  const logoStyles = [styles.logoStyle];
  if (menuToggled !== null) {
    const animation = new Animated.Value(menuToggled ? 0 : 1);

    Animated.timing(animation, {
      toValue: menuToggled ? 1 : 0,
      duration: 500,
      useNativeDriver: true
    }).start();

    const rotateInterpolate = animation.interpolate({
      inputRange: [0, 1],
      outputRange: ['0deg', '360deg']
    });
    const animatedStyles = { transform: [{ rotate: rotateInterpolate }] };
    logoStyles.push(animatedStyles);
  }

  return (
    <TouchableOpacity
      style = {styles.tabStyle}
      onPress = {onPress}
    >
      <Animated.View style = {logoStyles}>
        
      
      <Animated.Image
        style = {styles.tinyLogo}
        source = {{
          uri: 'https://reactnative.dev/img/tiny_logo.png',
        }}
      /></Animated.View>
    </TouchableOpacity>
  );
};
export default class App extends React.Component {
  state = {
    menuToggled: null
  }

  toggleMenu = () => {
    this.setState(prevState => {
      return { menuToggled: !prevState.menuToggled };
    });
  }

  render () {
    return (
      <View style = {styles.container}>
        <TabIcon
          onPress = {this.toggleMenu}
          menuToggled = {this.state.menuToggled}
        />
        
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'white'
  },  
  tinyLogo: {
    width: 150,
    height: 150,
    borderRadius: 100,
    margin: 8,
  },
});

и что я изменил до сих пор:

import React, { useRef, useState } from "react";
import { View, StyleSheet, Animated, Image, TouchableOpacity, Easing } from 'react-native';
import Constants from 'expo-constants';

const App = () => {
const spinValue = useRef(new Animated.Value(0)).current;
const [menuToggled, setMenuToggled] = useState([null]);



 toggleMenu = () => {
    setMenuToggled(menuToggled === "null" ? "menuToggled" : "null");
  }

const Spinner = ({
  onPress,
  menuToggled
}) => {
  const logoStyles = [styles.logoStyle];
 
    const animation = new Animated.Value(0);

  const go = () => {
    Animated.timing(animation, {
      toValue: 1,
      duration: 1500,
       easing: Easing.elastic(1),
      useNativeDriver: true
    }).start();

  }

    const rotateInterpolate = animation.interpolate({
      inputRange: [0, 1],
      outputRange: ['0deg', '360deg']
    });
    const animatedStyles = { transform: [{ rotate: rotateInterpolate }] };
    logoStyles.push(animatedStyles);
 

  return (
    <TouchableOpacity
     
      onPress = {go}  
    >
      <Animated.View style = {logoStyles}>
        
      
      <Animated.Image
        style = {styles.tinyLogo}
        source = {{
          uri: 'https://reactnative.dev/img/tiny_logo.png',
        }}
      /></Animated.View>
    </TouchableOpacity>
  );
};

  return (
  <View style = {styles.container}>
        <Spinner
          onPress = {toggleMenu} 
          menuToggled = {menuToggled}
          
        />
        
      </View>
  );
}






const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'white'
  },  
  tinyLogo: {
    width: 150,
    height: 150,
    borderRadius: 100,
    margin: 8,
  },
});

export default App;
Умерло ли Create-React-App?
Умерло ли Create-React-App?
В этом документальном фильме React.dev мы исследуем, мертв ли Create React App (CRA) и какое будущее ждет этот популярный фреймворк React.
Освоение React Native: Пошаговое руководство для начинающих
Освоение React Native: Пошаговое руководство для начинающих
React Native - это популярный фреймворк с открытым исходным кодом, используемый для разработки мобильных приложений. Он был разработан компанией...
В чем разница между react native и react ?
В чем разница между react native и react ?
React и React Native - два популярных фреймворка для создания пользовательских интерфейсов, но они предназначены для разных платформ. React - это...
От React к React Native: Руководство для начинающих по разработке мобильных приложений с использованием React
От React к React Native: Руководство для начинающих по разработке мобильных приложений с использованием React
Если вы уже умеете работать с React, создание мобильных приложений для iOS и Android - это новое приключение, в котором вы сможете применить свои...
Хуки React: что это такое и как их использовать
Хуки React: что это такое и как их использовать
Хуки React - это мощная функция библиотеки React, которая позволяет разработчикам использовать состояние и другие возможности React без написания...
0
0
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Есть несколько проблем. Сначала вы инициализировали menuToggled как [null], когда оно должно было быть null. Вы также забыли использовать onPress в TabIcon. Наиболее примечательной вещью было обертывание TabIcon в useCallback, чтобы предотвратить его постоянное воссоздание. Экспо-закуска:

import React, { useRef, useState, useCallback } from 'react';
import {
  View,
  StyleSheet,
  Animated,
  Image,
  TouchableOpacity,
} from 'react-native';
import Constants from 'expo-constants';

const App = () => {
  const spinValue = useRef(new Animated.Value(0)).current;
  const [menuToggled, setMenuToggled] = useState(null);

  const TabIcon = useCallback(({ onPress, menuToggled }) => {
    const logoStyles = [styles.logoStyle];
    // initialized base on menuToggled
    // if not done then it will take an additional button press to trigger
    // the animation
    const animation = useRef(new Animated.Value(menuToggled ? 0 : 1)).current;

    const startAnimation = () => {
      Animated.timing(animation, {
        toValue: menuToggled ? 1 :0,
        duration: 500,
        useNativeDriver: true,
      }).start();
    };

    const rotateInterpolate = animation.interpolate({
      inputRange: [0, 1],
      outputRange: ['0deg', '360deg'],
    });
    const animatedStyles = { transform: [{ rotate: rotateInterpolate }] };
    logoStyles.push(animatedStyles);
    return (
      <TouchableOpacity
        onPress = {() => {
          startAnimation();
          onPress?.();
        }}>
        <Animated.View style = {logoStyles}>
          <Animated.Image
            style = {styles.tinyLogo}
            source = {{
              uri: 'https://reactnative.dev/img/tiny_logo.png',
            }}
          />
        </Animated.View>
      </TouchableOpacity>
    );
  },[]);

  return (
    <View style = {styles.container}>
      <TabIcon
        onPress = {() => setMenuToggled((prev) => !prev)}
        menuToggled = {menuToggled}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'white',
  },
  tinyLogo: {
    width: 150,
    height: 150,
    borderRadius: 100,
    margin: 8,
  },
});

export default App;

Похоже, вы пытаетесь повернуть значок в навигаторе панели вкладок. Я не уверен, что компонент TabIcon хорошо свяжется с навигатором. Если это не даст мне знать

PhantomSpooks 12.01.2023 19:42

Ты бриллиант, Значит, я не так уж сильно ошибался тогда? Где был обратный вызов в версии класса? И благодарю вас.

JulesUK 12.01.2023 19:43

В вашем компоненте класса вы создали TabIcon вне функции рендеринга. Я думаю, что если вы переместите TabIcon за пределы компонента, вам не понадобится useCallback

PhantomSpooks 12.01.2023 19:50

Как мне это сделать? Я собирался спросить, возможно ли сделать что-то подобное, чтобы я мог добавить такие вещи к существующим вещам, таким как плоские списки.

JulesUK 12.01.2023 19:58
закуска.expo.dev/kpsW6JW5W
PhantomSpooks 12.01.2023 20:01

Спасибо за это, но он вращается вокруг оси? На этом новом вы переместили TabIcon за пределы рендера?

JulesUK 12.01.2023 20:07

Я только что заметил, что вращение не по оси, но я думаю, что это потому, что вращается вид, а не само изображение. Чтобы преодолеть это, вы можете просто анимировать само изображение, а не представление. Я также разработал демо-версию флэтлиста snack.expo.dev/pzQokudmP

PhantomSpooks 12.01.2023 23:40

Вау, спасибо, это потрясающе. Немного дерзко, но я пытаюсь добавить к нему отскок при нажатии, чтобы изображение увеличивалось и возвращалось назад во время вращения. Я задал еще один вопрос по этому поводу, но у вас, возможно, уже была идея, и еще раз спасибо, приятель.

JulesUK 12.01.2023 23:48
закуска.expo.dev/xd_y9v8rjE
PhantomSpooks 13.01.2023 00:34

Привет, спасибо за это. Он снова крутит его на оси? Эффект, который я ищу, похож на пульс или сердцебиение. Кроме того, вместо предопределенного изображения, насколько сложно было бы добавить разные изображения, такие как randomuser.me, и информацию о них в плоский список? Я не прошу вас сделать это, просто возможно ли это и как лучше всего двигаться дальше? Спасибо

JulesUK 13.01.2023 09:33

Я отсортировал вращение по оси следующим образом: const translateX = moveAnimValue.interpolate({ inputRange: [0, 1], outputRange: [0, 1], }); Я с нетерпением жду вашего мнения об этом случайном изображении и профиле! Спасибо

JulesUK 13.01.2023 09:39

Привет, я добавил эффект, который искал, следующим образом: }); Это то, о чем я говорил, чтобы заставить это работать, чтобы было легче научиться добавлять вещи в анимацию.

JulesUK 13.01.2023 10:37

Это было бы не слишком сложно. данные будут созданы с помощью хука useState и инициализированы пустым массивом. Затем при монтировании компонента вы должны получить данные от случайного пользователя, отформатировать их по мере необходимости, а затем установить для них данные.

PhantomSpooks 13.01.2023 18:07
закуска.expo.dev/yBNx2iPZy
PhantomSpooks 13.01.2023 18:09

Это блестяще, приятель, но я имел в виду создание изображений, предоставленных случайным пользователем, в качестве кликабельного значка. Вы очень талантливы и спасибо за вашу помощь

JulesUK 13.01.2023 18:19

Для этого вам нужно будет SpinButton принять исходную опору. Затем в компоненте Item вам нужно будет иметь свойство изображений и создать часть состояния для хранения индекса изображения. При нажатии кнопки вы устанавливаете индекс изображения на случайное число от 0 до images.length. Затем установите исходную опору на images[imageIndex]

PhantomSpooks 13.01.2023 19:17
закуска.expo.dev/73dwdhEyq
PhantomSpooks 13.01.2023 20:04

Вау еще раз, спасибо, приятель, мне пришлось вынуть setImageIndex(getRandomInt(0, images.length)); в противном случае он изменил изображение после первого вращения. Я собираюсь попробовать использовать это, чтобы посмотреть, смогу ли я добавить их в этот проект здесь: github.com/catalinmiron/react-native-movie-2.0-carousel Прежде чем я это сделаю, я столкнусь со многими проблемами, и так ли это? возможный? Также я хотел бы в конечном итоге анимировать несколько других элементов, но не уверен, следует ли мне использовать reanimated или LayoutAnimation. Вот где я путаюсь между 3! еще раз спасибо

JulesUK 13.01.2023 22:02

Я ничего не знаю об анимации макета, но я определенно предпочитаю reanimated анимационной библиотеке RN. Я просматриваю проект, но я действительно не понимаю, почему вы не можете добавить то, что у вас есть.

PhantomSpooks 14.01.2023 07:55

Привет, я хочу использовать это, потому что я хочу добавить анимацию к изображению профиля, а затем к общему макету, как это dribbble.com/shots/8257559-Movie-2-0 Если я смогу научиться делать что-то подобное или изучить код, который работает, тогда я был бы счастливым человеком. Если вы посмотрите на это, как лучше всего подойти к такому проекту. Также мы используем анимированные на этом не реанимированном. В чем разница и будет ли это иметь какое-либо значение для текущего проекта, и легко ли его изменить? спасибо аган

JulesUK 14.01.2023 17:13

Я думаю, что реанимация построена поверх реактивной реанимации. По умолчанию каждая анимация использует собственный драйвер, и значения анимации не нужно оборачивать в useRef. Я уверен, что есть еще что-то, но мне нравится внешний вид и легкость реанимации. Преобразование в реанимацию может потребовать больше усилий и, вероятно, не стоит затраченных усилий. Кроме того, вероятно, лучше хотя бы быть знакомым с нативным анимированным API реакции.

PhantomSpooks 15.01.2023 06:44

Давайте продолжим обсуждение в чате.

PhantomSpooks 15.01.2023 06:44

Привет, PhantomSpooks, не могли бы вы взглянуть на stackoverflow.com/questions/75152867/… пожалуйста. Я как бы разобрался с анимацией, но не могу включить ее в FlatList, как вы.

JulesUK 18.01.2023 08:16

Другие вопросы по теме