Bird
Raised Fist0
React Nativemobile~20 mins

React Native Reanimated - Mini App: Build & Ship

Choose your learning style10 modes available
Build: Simple Fade Animation
This screen shows a box that fades in and out when you tap a button below it.
Target UI
┌─────────────────────────────┐
│                             │
│          [  BOX  ]           │
│                             │
│                             │
│       [ Fade In/Out ]        │
└─────────────────────────────┘
Display a colored square box in the center of the screen.
Add a button labeled 'Fade In/Out' below the box.
When the button is tapped, the box should smoothly fade out if visible, or fade in if invisible.
Use React Native Reanimated for the fade animation.
Ensure the animation duration is about 500 milliseconds.
Starter Code
React Native
import React from 'react';
import { View, Button, StyleSheet } from 'react-native';
import Animated, { useSharedValue, useAnimatedStyle, withTiming } from 'react-native-reanimated';

export default function FadeBox() {
  const opacity = useSharedValue(1);

  const animatedStyle = useAnimatedStyle(() => {
    return {
      opacity: opacity.value
    };
  });

  const toggleFade = () => {
    // TODO: Add code to toggle opacity between 0 and 1 with animation
  };

  return (
    <View style={styles.container}>
      <Animated.View style={[styles.box, animatedStyle]} />
      <Button title="Fade In/Out" onPress={toggleFade} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#fff'
  },
  box: {
    width: 150,
    height: 150,
    backgroundColor: '#4a90e2',
    marginBottom: 20
  }
});
Task 1
Task 2
Task 3
Solution
React Native
import React from 'react';
import { View, Button, StyleSheet } from 'react-native';
import Animated, { useSharedValue, useAnimatedStyle, withTiming } from 'react-native-reanimated';

export default function FadeBox() {
  const opacity = useSharedValue(1);

  const animatedStyle = useAnimatedStyle(() => {
    return {
      opacity: opacity.value
    };
  });

  const toggleFade = () => {
    opacity.value = withTiming(opacity.value === 1 ? 0 : 1, { duration: 500 });
  };

  return (
    <View style={styles.container}>
      <Animated.View style={[styles.box, animatedStyle]} />
      <Button title="Fade In/Out" onPress={toggleFade} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#fff'
  },
  box: {
    width: 150,
    height: 150,
    backgroundColor: '#4a90e2',
    marginBottom: 20
  }
});

We use useSharedValue to hold the opacity state. The useAnimatedStyle hook returns a style object that updates the opacity of the box based on the shared value. The toggleFade function changes the opacity value between 1 and 0 using withTiming to animate the change smoothly over 500 milliseconds. This creates a fade in/out effect when the button is pressed.

Final Result
Completed Screen
┌─────────────────────────────┐
│                             │
│          [  BOX  ]           │
│                             │
│                             │
│       [ Fade In/Out ]        │
└─────────────────────────────┘
When the user taps the 'Fade In/Out' button, the blue box smoothly fades out if visible.
If the box is invisible, tapping the button fades it back in.
The fade animation lasts about half a second.
Stretch Goal
Add a sliding animation so the box moves up by 50 pixels while fading out and moves back down while fading in.
💡 Hint
Use another shared value for vertical position and animate it together with opacity using withTiming.

Practice

(1/5)
1.

What is the main purpose of useSharedValue in React Native Reanimated?

easy
A. To hold and update animation values that can change over time
B. To create static styles for components
C. To handle user input events
D. To navigate between screens

Solution

  1. Step 1: Understand useSharedValue role

    useSharedValue is designed to store values that can change and animate smoothly.
  2. Step 2: Compare with other options

    Static styles, user inputs, and navigation are unrelated to useSharedValue.
  3. Final Answer:

    To hold and update animation values that can change over time -> Option A
  4. Quick Check:

    useSharedValue = hold animation values [OK]
Hint: Remember: useSharedValue stores changing animation data [OK]
Common Mistakes:
  • Confusing useSharedValue with static styling
  • Thinking it handles user input or navigation
  • Assuming it triggers animations directly
2.

Which of the following is the correct syntax to create an animated style using useAnimatedStyle?

const animatedStyle = useAnimatedStyle(() => {
  return {
    opacity: sharedValue.value
  };
});
easy
A. const animatedStyle = useAnimatedStyle(() => { opacity: sharedValue.value });
B. const animatedStyle = useAnimatedStyle(() => ({ opacity: sharedValue.value }));
C. const animatedStyle = useAnimatedStyle(() => return { opacity: sharedValue.value });
D. const animatedStyle = useAnimatedStyle(() => [ opacity: sharedValue.value ]);

Solution

  1. Step 1: Check arrow function syntax

    Returning an object directly requires parentheses around the object: () => ({ ... }).
  2. Step 2: Validate each option

    const animatedStyle = useAnimatedStyle(() => ({ opacity: sharedValue.value })); uses correct syntax with parentheses. Options A, C, and D have syntax errors.
  3. Final Answer:

    const animatedStyle = useAnimatedStyle(() => ({ opacity: sharedValue.value })); -> Option B
  4. Quick Check:

    Arrow function returning object needs parentheses [OK]
Hint: Use parentheses to return object in arrow functions [OK]
Common Mistakes:
  • Missing parentheses around returned object
  • Using return without braces properly
  • Using array brackets instead of object braces
3.

Given the code below, what will be the opacity of the Animated.View after the shared value updates to 0.5?

const opacity = useSharedValue(1);

const animatedStyle = useAnimatedStyle(() => ({
  opacity: opacity.value
}));

// Later in code
opacity.value = 0.5;
medium
A. The opacity will remain 1
B. The opacity will become undefined
C. The opacity will update to 0.5 smoothly
D. The opacity will instantly jump to 0.5 without animation

Solution

  1. Step 1: Understand shared value update

    Updating opacity.value directly sets the value immediately without animation.
  2. Step 2: Direct assignment causes instant jump

    Reanimated updates the style instantly to 0.5 when using direct assignment, without smooth interpolation.
  3. Final Answer:

    The opacity will instantly jump to 0.5 without animation -> Option D
  4. Quick Check:

    Direct sharedValue.value = instant update [OK]
Hint: Direct shared value changes update instantly; use withTiming for smooth animation [OK]
Common Mistakes:
  • Thinking the value stays the same after update
  • Assuming it animates smoothly without withTiming
  • Confusing with non-animated style updates
4.

Identify the error in the following code snippet using React Native Reanimated:

const progress = useSharedValue(0);

const animatedStyle = useAnimatedStyle(() => {
  transform: [{ translateX: progress }]
});
medium
A. transform property should be a string, not an array
B. useSharedValue should be called inside useEffect
C. Missing .value when accessing shared value inside useAnimatedStyle
D. useAnimatedStyle cannot return an object

Solution

  1. Step 1: Check how shared values are accessed

    Inside useAnimatedStyle, shared values must be accessed with .value.
  2. Step 2: Identify the error in transform

    The code uses progress instead of progress.value, causing a runtime error.
  3. Final Answer:

    Missing .value when accessing shared value inside useAnimatedStyle -> Option C
  4. Quick Check:

    Access sharedValue.value inside animated styles [OK]
Hint: Always use .value to read shared values inside animated styles [OK]
Common Mistakes:
  • Forgetting .value on shared values
  • Calling useSharedValue inside effects incorrectly
  • Misunderstanding transform property format
5.

You want to create a button that scales up smoothly when pressed and returns to normal size when released. Which approach correctly uses React Native Reanimated to achieve this?

const scale = useSharedValue(1);

const animatedStyle = useAnimatedStyle(() => ({
  transform: [{ scale: scale.value }]
}));

// On press in
scale.value = withTiming(1.2, { duration: 200 });

// On press out
scale.value = withTiming(1, { duration: 200 });
hard
A. This approach correctly animates scale on press in and out using withTiming
B. You must use useState instead of useSharedValue for animation
C. withTiming cannot be used inside event handlers
D. Animated styles cannot animate transform properties

Solution

  1. Step 1: Check useSharedValue and useAnimatedStyle usage

    Using useSharedValue to hold scale and useAnimatedStyle to apply transform is correct.
  2. Step 2: Verify animation with withTiming

    withTiming smoothly animates the scale value on press in and out events.
  3. Step 3: Confirm event handler usage

    Assigning scale.value = withTiming(...) inside press handlers is valid and triggers animation.
  4. Final Answer:

    This approach correctly animates scale on press in and out using withTiming -> Option A
  5. Quick Check:

    UseSharedValue + withTiming = smooth press scale animation [OK]
Hint: Use withTiming on shared values for smooth press animations [OK]
Common Mistakes:
  • Using useState instead of useSharedValue for animation
  • Thinking withTiming can't be used in event handlers
  • Believing transform can't animate
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard