如何修复React-Native动画以仅对“ this”组件进行动画处理

时间:2019-08-01 00:42:21

标签: javascript reactjs react-native

我在井字游戏中有一个Tile类。我的目标是为图块内容的外观设置动画,并且仅对最近按下的图块的外观进行动画处理。我的问题有两个: 1:动画仅在第一次平铺时起作用,而不是每次都起作用 2:动画会影响所有图块

编辑:向value.setValue(0);添加了useEffect(),以便每次按下时重置动画值。剩下的唯一问题是,每次按下时,所有Tile组件都会设置动画,而我只希望<Tile>发生变化的props.contents组件具有动画效果。

如果我改而将Animated.timing函数放在onSelection内,则只有按下的动画才能按预期进行,但是由于这是通过套接字连接进行的,因此两个客户端的tile都需要进行动画处理,在这种情况下,只有按下图块的客户端才能看到动画。 (因为动画功能不再位于useEffect()中)

编辑2:尝试更改useEffect()以包括依赖项数组和条件语句,以及仅包括https://reactjs.org/docs/hooks-effect.html中引用的依赖项数组

Tile.js

import React, { useEffect, useState } from "react";
import SocketContext from "../socket-context";
import { View, Animated, TouchableOpacity } from "react-native";
import styles from "../assets/styles/main-style";

function Tile(props) {
  function onSelection(row, col, socket) {
    props.onSelection(row, col, socket);
  }
  let [value] = useState(new Animated.Value(0));

  // useEffect(() => {
  //  value.setValue(0);
  //  Animated.timing(value, {
  //    toValue: 100,
  //    duration: 10000,
  //    useNativeDriver: true
  //  }).start();
  // });

  (EDIT 2-a):
   useEffect(() => {
    if (props.contents !== {marker: null}) {
      return
    } else {
     value.setValue(0);
     Animated.timing(value, {
       toValue: 100,
       duration: 10000,
       useNativeDriver: true
     }).start();
    }
   }, [props.contents]);

  (EDIT 2-b):
   useEffect(() => {
     value.setValue(0);
     Animated.timing(value, {
       toValue: 100,
       duration: 10000,
       useNativeDriver: true
     }).start();
   }, [props.contents]);

  let animated_opacity = value.interpolate({
    inputRange: [0, 100],
    outputRange: [0.0, 1.0]
  });

  let animated_rotation = value.interpolate({
    inputRange: [0, 50, 100],
    outputRange: ["0deg", "180deg", "360deg"]
  });

  return (
    <SocketContext.Consumer>
      {socket => (
        <View style={styles.grid_cell}>
          <TouchableOpacity
            style={styles.cell_touchable}
            onPress={() => onSelection(props.row, props.col, socket)}
          >
            <Animated.Text
              style={{
                fontFamily: "BungeeInline-Regular",
                fontSize: 65,
                textAlign: "center",
                color: "#fff",
                opacity: animated_opacity,
                transform: [{ rotateX: animated_rotation }]
              }}
            >
              {props.contents.marker}
            </Animated.Text>
          </TouchableOpacity>
        </View>
      )}
    </SocketContext.Consumer>
  );
}

export default Tile;

如何在Grid.js中使用图块

import React from "react";
import { View } from "react-native";
import Tile from "../components/Tile";
import styles from "../assets/styles/main-style";

function Grid(props) {
  function onGridSelection(row, col, socket) {
    props.onGridSelection(row, col, socket);
  }

  const grid = props.grid.map((rowEl, row) => {
    const cells = rowEl.map((cellEl, col) => {
      return (
        <Tile
          row={row}
          col={col}
          contents={cellEl}
          onSelection={onGridSelection}
        />

      );
    });
    return (
      <View style={styles.grid_row} key={row}>
        {cells}
      </View>
    );
  });
  return <View style={styles.grid}>{grid}</View>;
}

export default Grid;

我的目标是在每次按下图块的props.contents发生变化时,让动画运行,并且对该图块 only 起作用。我不确定是否每次按下新的图块时都会重新渲染整个网格(props.grid),并以某种方式创建了此不需要的功能。

但是,动画 only 仅在第一次平铺时运行。并且它可以在板上的每个图块上运行(我知道这是因为我遇到了一个问题,即以前的游戏内存正在泄漏到新游戏中〜一个单独的问题)

1 个答案:

答案 0 :(得分:1)

现在,您的useEffect在每个渲染器上运行,因为它没有提供任何依赖项作为第二个参数。另一个问题是跳过了第一次渲染的效果。

如果图块内容标记的初始值为null,则可以使用以下方法解决此问题:

  useEffect(() => {
    // exit early if the Tile contents are the initial content values
    // which means the animation shouldn't run
    if (props.contents.marker === null) {
      return;
    }
    value.setValue(0);
    Animated.timing(value, {
      toValue: 100,
      duration: 10000,
      useNativeDriver: true
    }).start();
  // note the addition of the dependency array here so this effect only runs
  // when props.contents.marker changes
  }, [props.contents.marker]);

有关useEffect的第二个参数的更多信息,请参见https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects