React Native Animated не работает при первом нажатии

Я создаю покерный стол, используя нативную реакцию, и я хочу, чтобы при щелчке стула происходила анимация (расстановка стульев вокруг стола).

Но анимация не работает при первом нажатии, а работает при втором нажатии.

Пожалуйста, проверьте изображение нижеReact Native Animated не работает при первом нажатии

Вы можете видеть, что вокруг стола стоят 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

Пожалуйста помоги.

попробуйте добавить рабочий код (загрузите эту часть в закуску), чтобы мы могли увидеть проблему

chikabala 30.03.2022 13:14

это ссылка на полный код для экрана- закуска.expo.dev/sd7yF5CzZ

yogesh kumar 30.03.2022 13:17
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
2
31
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Решение состоит в том, чтобы добавить 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, чтобы гарантировать, что анимация будет запускаться при первом рендеринге.

спасибо за ответ, но извините, это не сработало, пожалуйста, предложите что-нибудь еще

yogesh kumar 30.03.2022 13:45

@yogeshkumar, что именно у тебя не сработало?

chikabala 30.03.2022 14:01

при первом клике(любой стул) код работает(как работает console.info) но анимация не происходит

yogesh kumar 30.03.2022 14:05

@yogeshkumar забыл сказать вам, что вы должны инициировать shiftBy числом> 0, например: 1

chikabala 30.03.2022 14:29

вот закуска к нему закуска.expo.dev/e_Yki70nv

chikabala 30.03.2022 14:30

Другие вопросы по теме

Похожие вопросы

Как создавать собственные макеты/фигуры, используя элемент холста в реакции/javascript
Невозможно изменить входное значение в React
Как установить параметры выбора Formik FieldArray для различных значений индекса на основе другого выбора
React JS JSX, не могу понять полезность обратного вызова, переданного в параметре внутри функции без статистики
Как изменить формат vAxis для определенной серии targetAxisIndex в React Google Chart
Почему я не могу настроить таргетинг на отображаемый <li> с помощью кнопки, сопоставленной с ним, с помощью React?
Проверьте, находится ли параметр URL в списке разрешенных параметров и маршрутизируйте его соответствующим образом
Как запретить пользователю не добавлять один и тот же язык?
Все столбцы не отображаются должным образом в динамической таблице pdfMake в ответ
Почему мое значение массива меняется, когда я устанавливаю состояние другого объекта в ответ?