Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

withRepeat using array will not reverse #6799

Closed
odogono opened this issue Dec 9, 2024 · 2 comments · Fixed by #6881
Closed

withRepeat using array will not reverse #6799

odogono opened this issue Dec 9, 2024 · 2 comments · Fixed by #6881
Assignees
Labels
Platform: Android This issue is specific to Android Platform: iOS This issue is specific to iOS Repro provided A reproduction with a snippet of code, snack or repo is provided

Comments

@odogono
Copy link
Contributor

odogono commented Dec 9, 2024

Description

A shared value which contains a number array will not behave as expected with a withRepeat hook.

If the parameters of the withRepeat hook are set to reverse, the sharedValue will increment to the desired value correctly, but then instead of reversing back to the original value, it will remain.

I have checked the behaviour with object ( {x:0} ) and number values, and they behave as expected.

I did some limited debugging, and I observe that the repeat animation.startValue is referentially the same as the nextAnimation.current when an array is used during the "forward" part of the animation, but when an object or a number is used the value reference is different (within /packages/react-native-reanimated/src/animation/repeat.ts)

Steps to reproduce

  1. create a shared value containing a number array
const arrayValue = useSharedValue([0]);
  1. set up a repeated timing
arrayValue.value = withRepeat(
      withTiming([30], { duration: 1000 } ),
      2,
      true);
  1. Observe the value changing
useAnimatedReaction(
  () => arrayValue.value,
  (value) => {
        console.log('value', value);
   }
);

Snack or a link to a repository

https://snack.expo.dev/@odogono/uplifting-green-waffles

Reanimated version

3.16.3

React Native version

0.76.3

Platforms

Android, iOS

JavaScript runtime

None

Workflow

None

Architecture

Fabric (New Architecture)

Build type

None

Device

iOS simulator

Device model

No response

Acknowledgements

Yes

@github-actions github-actions bot added Repro provided A reproduction with a snippet of code, snack or repo is provided Platform: Android This issue is specific to Android Platform: iOS This issue is specific to iOS labels Dec 9, 2024
@odogono odogono changed the title withRepeat using array will not reverse withRepeat using array will not reverse Dec 9, 2024
@patrycjakalinska patrycjakalinska self-assigned this Jan 8, 2025
@patrycjakalinska
Copy link
Contributor

Hi @odogono, thank you for the issue! Nice job identifying the cause of the bug c: I dug deeper and it seems like that assigning array value at some point to both animation.startValue and nextAnimation.current created a reference between them. I've already opened a PR that addresses this problem.

Feel free to take a look, and let me know if you have any further feedback! c:

github-merge-queue bot pushed a commit that referenced this issue Jan 30, 2025
## Summary

Fixes #6799. Shared value which contains a number array will not behave
as expected with a `withRepeat` hook. Because it was an array the
`animation.startValue` and `nextAnimation.current` became connected by
reference, and therefore `startValue` was rising as `current` instead of
staying a actual `startValue`. I discovered that in `arrayOnStart`,
`animation.current === value` caused a referenced so i spread it.

## Test plan

Example code:

```js
import { Text, SafeAreaView, StyleSheet } from 'react-native';
import { useEffect } from 'react';

import {
  useAnimatedReaction, 
  useSharedValue, 
  withRepeat, 
  withTiming 
} from 'react-native-reanimated';


export default function App() {

  const arrayValue = useSharedValue([0]);
  const objValue = useSharedValue({x:0});  
  const numberValue = useSharedValue(0);

  const textValue = useSharedValue('0');

  useEffect( () => {    
    const duration = 300;

    // ❌ changes from [0,0,0] to [30,30,30] but then stops
    arrayValue.value = withRepeat(
      withTiming([30], { duration} ),
      2,
      true);

    // ✅ repeats from 0 to 30 and back to 0
    numberValue.value = withRepeat(
      withTiming(30, { duration} ),
      2,
      true);

  // ✅ repeats from {x:0,y:0,z:0} to {x:30,y:30,z:30} and back to {x:0,y:0,z:0}
    objValue.value = withRepeat(
      withTiming({x: 30}, { duration} ),
      2,
      true);
  },[]);

  useAnimatedReaction(
    () => [arrayValue.value, numberValue.value, objValue.value],
    ([arrayValue, numberValue, objValue]) => {
      // ✅ works - value reaches 30, then back to 0
      // textValue.value = `${numberValue.toFixed(2)}`;

      // ✅ works - value reaches 30, then back to 0
      // textValue.value = `${objValue.x.toFixed(2)}`;

      // ❌ value reaches 30, then remains
      textValue.value = `${arrayValue[0].toFixed(2)}`

      console.log('value:', textValue.value);
    }
  )

  return (
    <SafeAreaView style={styles.container}>
        <Text style={styles.text}>See console.log</Text>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
  text: {
    margin: 24,
    fontSize: 18,
    fontWeight: 'bold',
    textAlign: 'center',
  }
});

```
@odogono
Copy link
Contributor Author

odogono commented Jan 30, 2025

That's perfect - thank you so much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Platform: Android This issue is specific to Android Platform: iOS This issue is specific to iOS Repro provided A reproduction with a snippet of code, snack or repo is provided
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants