Jim*_*Jim 5 javascript reactjs react-native
我在井字棋游戏中有一个瓷砖类。我的目标是为磁贴内容的外观设置动画,并且只显示最近按下的磁贴的外观。我的问题有两个:1:动画仅适用于第一次按瓷砖,而不是每次都适用 2:动画影响所有瓷砖
编辑:添加value.setValue(0);到useEffect()每次按下重置动画值。唯一剩下的问题是所有 Tile 组件在每次按下时都会动画,而我只希望更改的<Tile>组件有动画props.contents。
如果我改为将Animated.timing函数放入onSelection,则只有按下的动画会按预期进行,但由于这是通过套接字连接,因此两个客户端的图块都需要动画,在这种情况下,只有按下图块的客户端才能看到动画。(因为动画功能已经不在了useEffect())
编辑 2:尝试更改useEffect()以包含依赖项数组和条件语句以及仅包含https://reactjs.org/docs/hooks-effect.html 中引用的依赖项数组
瓷砖.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;
Run Code Online (Sandbox Code Playgroud)
如何在 Grid.js 中使用 Tile
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;
Run Code Online (Sandbox Code Playgroud)
我的目标是让动画在瓷砖props.contents发生变化时运行,每次按下瓷砖时,并且仅针对该瓷砖。我不确定props.grid每次按下新图块时整个网格 ( ) 是否都被重新渲染,这是否以某种方式创建了这个不需要的功能。
然而,动画只在第一次瓷砖印刷时运行。它为板上的每个图块运行(我知道这一点,因为我有一个问题,以前的游戏内存泄漏到新游戏〜一个单独的问题)
现在,您useEffect在每个渲染上运行,因为它没有作为第二个参数提供的任何依赖项。另一个问题是跳过第一次渲染的效果。
如果图块内容标记的初始值为空,那么您可以使用以下方法解决此问题:
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]);
Run Code Online (Sandbox Code Playgroud)
有关 的第二个参数的更多信息,请参阅https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effectsuseEffect