Bird
Raised Fist0
React Nativemobile~20 mins

useEffect hook in React Native - Mini App: Build & Ship

Choose your learning style10 modes available
Build: Timer Screen
This screen shows a timer that counts seconds after the screen loads. It uses the useEffect hook to start and clean up the timer.
Target UI
-------------------
| Timer Screen    |
|-----------------|
| Seconds: 0      |
|                 |
| [Reset Timer]   |
-------------------
Display a seconds counter starting at 0
Use useEffect to start a timer that increments seconds every second
Clean up the timer when the component unmounts
Add a Reset Timer button that sets seconds back to 0
Starter Code
React Native
import React, { useState, useEffect } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';

export default function TimerScreen() {
  const [seconds, setSeconds] = useState(0);

  // TODO: Use useEffect to start timer and clean up

  return (
    <View style={styles.container}>
      <Text style={styles.timerText}>Seconds: {seconds}</Text>
      <Button title="Reset Timer" onPress={() => setSeconds(0)} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  timerText: {
    fontSize: 32,
    marginBottom: 20,
  },
});
Task 1
Task 2
Solution
React Native
import React, { useState, useEffect } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';

export default function TimerScreen() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setSeconds(prev => prev + 1);
    }, 1000);

    return () => clearInterval(interval);
  }, []);

  return (
    <View style={styles.container}>
      <Text style={styles.timerText}>Seconds: {seconds}</Text>
      <Button title="Reset Timer" onPress={() => setSeconds(0)} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  timerText: {
    fontSize: 32,
    marginBottom: 20,
  },
});

We use the useEffect hook to start a timer when the screen loads. The timer uses setInterval to add 1 to the seconds every 1000 milliseconds (1 second). The empty dependency array [] means this effect runs only once when the component mounts. We return a cleanup function that clears the interval when the component unmounts to avoid memory leaks. The Reset button sets the seconds back to 0 immediately.

Final Result
Completed Screen
-------------------
| Timer Screen    |
|-----------------|
| Seconds: 12     |
|                 |
| [Reset Timer]   |
-------------------
Seconds number increases by 1 every second automatically
Pressing Reset Timer sets seconds back to 0 immediately
Stretch Goal
Add a Pause/Resume button to stop and start the timer
💡 Hint
Use a state variable to track if timer is running and conditionally start/stop the interval inside useEffect

Practice

(1/5)
1. What does the useEffect hook do in a React Native component?
easy
A. Defines the component's UI layout
B. Declares a new state variable
C. Runs code after the component renders or updates
D. Handles user input events

Solution

  1. Step 1: Understand the purpose of useEffect

    The useEffect hook is designed to run side effects after rendering or updating a component.
  2. Step 2: Compare with other React Native features

    Declaring state is done with useState, UI layout is JSX, and event handling uses props or handlers, not useEffect.
  3. Final Answer:

    Runs code after the component renders or updates -> Option C
  4. Quick Check:

    useEffect runs after render/update = A [OK]
Hint: useEffect runs code after render or update [OK]
Common Mistakes:
  • Confusing useEffect with useState
  • Thinking useEffect defines UI
  • Assuming useEffect handles events directly
2. Which of the following is the correct syntax to run useEffect only once when the component mounts?
easy
A. useEffect(() => { /* code */ });
B. useEffect(() => { /* code */ }, []);
C. useEffect(() => { /* code */ }, true);
D. useEffect(() => { /* code */ }, null);

Solution

  1. Step 1: Identify how to run useEffect once

    Passing an empty dependency array [] makes useEffect run only once after the first render.
  2. Step 2: Analyze other options

    Omitting the dependency array runs on every render, and passing non-array values like true or null causes a type error since the second argument must be an array.
  3. Final Answer:

    useEffect(() => { /* code */ }, []); -> Option B
  4. Quick Check:

    Empty array means run once = A [OK]
Hint: Empty array runs useEffect once on mount [OK]
Common Mistakes:
  • Forgetting the empty array causes repeated runs
  • Using non-empty arrays thinking it runs once
  • Omitting the dependency array
3. Consider this React Native code snippet where the setCount calls are in an event handler after initial mount:
const [count, setCount] = useState(0);
useEffect(() => {
  console.log('Count is', count);
}, [count]);

setCount(1);
setCount(2);

What will be printed in the console?
medium
A. Count is 0
B. Count is 1
C. Count is 1 and then Count is 2
D. Count is 2

Solution

  1. Step 1: Understand useEffect dependency on count

    The effect runs after render when count changes. It logs the current count value.
  2. Step 2: Analyze setCount calls

    Calling setCount(1) then immediately setCount(2) causes React to batch updates, so only the last value (2) triggers a render and effect.
  3. Final Answer:

    Count is 2 -> Option D
  4. Quick Check:

    Last setCount triggers effect with 2 = C [OK]
Hint: Last state update triggers useEffect with that value [OK]
Common Mistakes:
  • Thinking both setCount calls trigger separate effects
  • Expecting initial count log
  • Ignoring React's batching of state updates
4. What is wrong with this useEffect usage?
useEffect(() => {
  fetchData();
}, fetchData);

Assuming fetchData is a function defined outside the component.
medium
A. Dependency array should be an array, not a function
B. fetchData should be called inside useEffect, not outside
C. useEffect cannot call functions
D. No dependency array means it runs only once

Solution

  1. Step 1: Check dependency argument type

    The second argument to useEffect must be an array listing dependencies, not a function.
  2. Step 2: Understand correct usage

    To run effect when fetchData changes, pass [fetchData]. Passing just fetchData causes a type error.
  3. Final Answer:

    Dependency array should be an array, not a function -> Option A
  4. Quick Check:

    Dependency must be array = B [OK]
Hint: Dependency argument must be an array [OK]
Common Mistakes:
  • Passing a function instead of an array
  • Omitting dependency array thinking it's optional
  • Confusing function call with dependency list
5. You want to fetch user data only when the user ID changes in a React Native component. Which useEffect hook setup is best?
hard
A. useEffect(() => { fetchUserData(); }, [userId]);
B. useEffect(() => { fetchUserData(userId); }, [fetchUserData]);
C. useEffect(() => { fetchUserData(); });
D. useEffect(() => { fetchUserData(); }, []);

Solution

  1. Step 1: Identify when to run fetchUserData

    The fetch should run only when userId changes, so userId must be in the dependency array.
  2. Step 2: Evaluate options

    useEffect(() => { fetchUserData(); }, []); runs only once, ignoring userId changes. useEffect(() => { fetchUserData(); }); runs every render. useEffect(() => { fetchUserData(userId); }, [fetchUserData]); depends on fetchUserData, which is likely stable or external, not userId.
  3. Final Answer:

    useEffect(() => { fetchUserData(); }, [userId]); -> Option A
  4. Quick Check:

    Dependency array with userId triggers fetch on change = D [OK]
Hint: Put changing values in dependency array [OK]
Common Mistakes:
  • Leaving dependency array empty when value changes
  • Omitting dependency array causing too many fetches
  • Using wrong dependencies causing missed updates
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