【问题标题】:react-animated loop becomes very buggy after a short time, React Native, Animated.Textreact-animated 循环在短时间内变得非常错误,React Native,Animated.Text
【发布时间】:2021-06-24 13:22:28
【问题描述】:

我最近开始尝试在我尝试在 React Native 中制作的应用程序中使用动画。 我不是 100% 熟悉 React Animated,但我相信我尝试制作的动画非常简单。

我有一个屏幕,我想让一些文本从右侧滑入,暂停几秒钟,然后向左滑出,然后再重复一些其他文本。

虽然我确实做到了,但动画和文本很快变得非常有问题(也就是没有流畅的动画,一段时间后根本没有动画,文本会很快随机变化,等等......)。

我不知道这是为什么,我尝试将 useNativeDriver 切换到 true 以希望获得更流畅的动画,但随后我收到错误消息,提示我无法使用样式属性“left”。

代码如下:

import React, { useState, useCallback, useEffect } from 'react';
import { Text, View, StyleSheet, Animated } from 'react-native';
import Constants from 'expo-constants';

function App() {
  let [wordsAnim] = useState(new Animated.Value(60)),
    runAnimation = () => {
      wordsAnim.setValue(60);
      Animated.sequence([
        Animated.timing(wordsAnim, {
          toValue: 0,
          duration: 1500,
          useNativeDriver: false,
        }),
        Animated.timing(wordsAnim, {
          toValue: -60,
          duration: 1500,
          delay: 3000,
          useNativeDriver: false,
        }),
      ]).start(({ finished }) => {
        runAnimation();
        updateWord();
      });
    };

  //An array of random words to display
  const words = ['First', 'Second', 'Third', 'Fourth'];

  //First word displayed is a random word from the array
  const [word, changeWord] = useState(
    words[Math.floor(Math.random() * words.length)]
  );

  //Update the word displayed with another random word from the array
  const updateWord = () => {
    const index = Math.floor(Math.random() * words.length);
    changeWord(words[index]);
  };

  useEffect(() => {
    runAnimation();
  });

  return (
    <View style={styles.container}>
      <Animated.Text
        style={{
          margin: 24,
          fontSize: 18,
          fontWeight: 'bold',
          textAlign: 'center',
          left: wordsAnim.interpolate({
            inputRange: [0, 100],
            outputRange: ['0%', '100%'],
          }),
        }}>
        {word}
      </Animated.Text>
    </View>
  );
}

export default App;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
});

你也可以找到这个例子here

我也会为 React Native 提供关于动画或其他任何内容的任何提示, 谢谢!!

【问题讨论】:

  • 我对 React 动画了解不多,但我想知道您的 useEffect 是否有问题?在编写代码时,runAnimation 将被重新触发 "after every completed render"。也许它应该只在组件挂载上运行:useEffect(runAnimation, []),或者当某些道具发生变化时:useEffect(runAnimation, [propName])
  • 确实,我已经更新了代码并添加了callBacks,现在可以正常运行了!谢谢!

标签: javascript react-native performance expo react-animated


【解决方案1】:

正如@David784 所指出的,我的runAnimation 在每次完成渲染后都会重新触发。它应该只在组件安装上运行。 添加一些回调就可以了!

下面的工作代码:

import React, { useState, useCallback, useEffect } from 'react';
import { Text, View, StyleSheet, Animated } from 'react-native';
import Constants from 'expo-constants';

function App() {
  let [wordsAnim] = useState(new Animated.Value(60)),
    runAnimation = useCallback(() => {
      wordsAnim.setValue(60);
      Animated.sequence([
        Animated.timing(wordsAnim, {
          toValue: 0,
          duration: 1500,
          useNativeDriver: false,
        }),
        Animated.timing(wordsAnim, {
          toValue: -60,
          duration: 1500,
          delay: 3000,
          useNativeDriver: false,
        }),
      ]).start(({ finished }) => {
        updateWord();
        runAnimation();
      });
    }, [updateWord, wordsAnim]);

  //An array of random words to display
  const words = ['First', 'Second', 'Third', 'Fourth'];

  //First word displayed is a random word from the array
  const [word, changeWord] = useState(
    words[Math.floor(Math.random() * words.length)]
  );

  //Update the word displayed with another random word from the array
  const updateWord = useCallback(() => {
    const index = Math.floor(Math.random() * words.length);
    changeWord(words[index]);
  }, [words]);

  useEffect(() => {
    runAnimation();
  }, [runAnimation]);

  return (
    <View style={styles.container}>
      <Animated.Text
        style={{
          margin: 24,
          fontSize: 18,
          fontWeight: 'bold',
          textAlign: 'center',
          left: wordsAnim.interpolate({
            inputRange: [0, 100],
            outputRange: ['0%', '100%'],
          }),
        }}>
        {word}
      </Animated.Text>
    </View>
  );
}

export default App;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-05
    • 2021-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多