我在井字游戏中有一个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 仅在第一次平铺时运行。并且它可以在板上的每个图块上运行(我知道这是因为我遇到了一个问题,即以前的游戏内存正在泄漏到新游戏中〜一个单独的问题)
答案 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。