Я создаю покерный стол, используя нативную реакцию, и я хочу, чтобы при щелчке стула происходила анимация (расстановка стульев вокруг стола).
Но анимация не работает при первом нажатии, а работает при втором нажатии.
Пожалуйста, проверьте изображение ниже
Вы можете видеть, что вокруг стола стоят 8 стульев. Я хочу, чтобы всякий раз, когда я нажимаю на любой стол, вращение должно происходить таким образом, чтобы стол, на который я нажал, заменял зеленый стол (внизу).
Проблема в том, что при первом клике код внутри useEffect срабатывает, но анимация все равно не происходит.
Вот код
import {
Animated,
} from 'react-native';
function HomeScreen() {
const [shiftBy, setSiftBy] = React.useState(0);
const [p1InitialPosition] = React.useState(new Animated.ValueXY({ x: 180, y: 30 }));
const [p2InitialPosition] = React.useState(new Animated.ValueXY({ x: 325, y: 125 }));
const [p3InitialPosition] = React.useState(new Animated.ValueXY({ x: 338, y: 230 }));
const [p4InitialPosition] = React.useState(new Animated.ValueXY({ x: 335, y: 370 }));
const [p5InitialPosition] = React.useState(new Animated.ValueXY({ x: 180, y: 470 }));
const [p6InitialPosition] = React.useState(new Animated.ValueXY({ x: 30, y: 370 }));
const [p7InitialPosition] = React.useState(new Animated.ValueXY({ x: 30, y: 230 }));
const [p8InitialPosition] = React.useState(new Animated.ValueXY({ x: 40, y: 125 }));
const chairs = React.useMemo(() => {
return [
p1InitialPosition,
p2InitialPosition,
p3InitialPosition,
p4InitialPosition,
p5InitialPosition,
p6InitialPosition,
p7InitialPosition,
p8InitialPosition,
];
}, [
p1InitialPosition,
p2InitialPosition,
p3InitialPosition,
p4InitialPosition,
p5InitialPosition,
p6InitialPosition,
p7InitialPosition,
p8InitialPosition,
]);
// updated/animated positions
React.useEffect(() => {
const np = [];
for (let i = 0; i < chairs.length; i++) {
console.info(chairs[i], chairs[(i + shiftBy) % 8]);
np.push(
Animated.timing(chairs[i], {
toValue: chairs[(i + shiftBy) % 8],
duration: 800,
useNativeDriver: true,
}),
);
}
Animated.parallel(np).start();
console.info('');
}, [shiftBy]);
return (
<SafeAreaView style = {styles.container}>
<Image
onLayout = {event => {
const layout = event.nativeEvent.layout;
console.info('height:', layout.height);
console.info('width:', layout.width);
console.info('x:', layout.x);
console.info('y:', layout.y);
}}
source = {require('../../assets/image/table/table.png')}
style = {{
height: '100%',
width: '100%',
}}
/>
{/* p1 */}
<Animated.View
style = {{
position: 'absolute',
transform: [{ translateX: p1InitialPosition.x }, { translateY: p1InitialPosition.y }],
}}>
<TouchableOpacity
// disabled = {selectedChair}
onPress = {() => setSiftBy(4)}>
<Icon name = "chair" size = {30} color = "blue" />
</TouchableOpacity>
</Animated.View>
{/* p2 */}
<Animated.View
style = {{
position: 'absolute',
transform: [{ translateX: p2InitialPosition.x }, { translateY: p2InitialPosition.y }],
}}>
<TouchableOpacity
// disabled = {selectedChair}
onPress = {() => setSiftBy(3)}>
<Icon name = "chair" size = {30} color = "skyblue" />
</TouchableOpacity>
</Animated.View>
{/* p3 */}
{/* p4 */}
{/* p5 */}
{/* p6 */}
{/* p7 */}
{/* p8 */}
</SafeAreaView>
);
}
export default HomeScreen;это ссылка для завершения кода для экрана - закуска.expo.dev/sd7yF5CzZ
Пожалуйста помоги.
это ссылка на полный код для экрана- закуска.expo.dev/sd7yF5CzZ





Решение состоит в том, чтобы добавить useLayoutEffect в ваш код:
React.useLayoutEffect(() => {
const np = [];
for (let i = 0; i < chairs.length; i++) {
console.info(chairs[i], chairs[(i + shiftBy) % 8]);
np.push(
Animated.timing(chairs[i], {
toValue: chairs[(i + shiftBy) % 8],
duration: 800,
useNativeDriver: true,
}),
);
}
Animated.parallel(np).start();
console.info('');
}, [shiftBy]);
Объяснение
Поскольку useEffect обратные вызовы вызываются после фазы фиксации рендеринга и, следовательно, после цикла рендеринга, а LayoutAnimation.configureNext предназначен для «подготовки» следующего рендера, уже слишком поздно вызывать его внутри useEffect.
Таким образом, решение состоит в том, чтобы использовать useLayoutEffect вместе с useEffect, чтобы гарантировать, что анимация будет запускаться при первом рендеринге.
спасибо за ответ, но извините, это не сработало, пожалуйста, предложите что-нибудь еще
@yogeshkumar, что именно у тебя не сработало?
при первом клике(любой стул) код работает(как работает console.info) но анимация не происходит
@yogeshkumar забыл сказать вам, что вы должны инициировать shiftBy числом> 0, например: 1
вот закуска к нему закуска.expo.dev/e_Yki70nv
попробуйте добавить рабочий код (загрузите эту часть в закуску), чтобы мы могли увидеть проблему