React Native LogoNm Logo

🐞 React Native bug squasher

Version 2.0, from the University of Maine's New Media program

React Native and Expo make it surprisingly easy to code a cross-platform app, but beginners can still get hung up on unfamiliar or confusing error messages. To help solve your error, type it into the search box or jump to a list of debugging techniques.

Brought to you by the Just-in-Time Learning platform of the University of Maine's New Media major. Submit a comment or suggestion via ude.eniam@otiloppij or @jonippolito.

Search for your error:

    Specific error messages

  1. 🐞 Unexpected token

      This is usually a delimiter (punctuation mark) out of place.

    • Check to ensure there is an opening and closing version for each (...) [...] {...} in your code.
    • Look for missing commas in your objects, including styles.
    • Click Prettier and check for correct indenting. Every function definition should start with a { and end with a } at the same horizontal distance from the left edge. Functions at the "root" level should have their delimiters all the way to the left. âš ī¸ If you make a significant error, it may prevent Prettier from working, but you can still check the indenting by hand.
    • Make sure you haven't mixed up a colon (:) for a semicolon (;). For example, the end of every function definition may have a semicolon after the final }.
    • If the error message flags the last line of your code, it's still very possible the missing delimiter occurred earlier and the computer only realized it was missing when it reached the end.
  2. 🐞 Constructor requires new...

      That usually means you didn't import a needed component, custom or default.

    • Check your import statement/s at top. StyleSheet is a common component to forget.
  3. 🐞 Maximum update depth exceeded

      This can happen when a component is stuck refreshing the screen endlessly.

    • Go to the component that triggers this error when loaded, then comment out the entire contents of return. Add bits back one at a time until you identify the code that's generating the infinite loop.
  4. 🐞 Module not definedor Unable to resolve module or Expected component but found object

      This usually means you forgot to define or export a component. Or you might not have used the exact same name--with identical capitalization and spelling--for the component in its various occurrences. (Watch out for plurals inside camelCase words, eg petScreen versus petsScreen.) Check your naming consistency in:

    • The function definition (const WelcomeScreen = () => {...})
    • The export statement (export default WelcomeScreen)
    • The component's file name (WelcomeScreen.js)
    • Any import statements (import WelcomeScreen from "./WelcomeScreen")
    • Your navigation stack (component={ WelcomeScreen }).
  5. 🐞 Minified error #...

      A "minified" error is too long to fit in the phone screen, but includes a URL you can load in a separate browser window. The component that threw the error is often listed at the end (eg, Input[]).

    • Copy and paste the associated URL (https://reactjs.org/docs/error-decoder.html/?....) into a browser to see an "error decoder" page, or search for the error number in Google.
    • See the specific examples (#130, #152, etc.) listed in this document.
  6. 🐞 Minified React error #31

      The URL for this minified error (https://reactjs.org/docs/error-decoder.html?invariant=31....) leads to an error page that says Objects are not valid as a React child. This can sometimes mean you tried passing the wrong kind of attribute to a child component. For example, you can't pass an object or an attribute directly inside JSX tags.

    • If you meant to render a collection of children, use an array instead
    • If you meant to pass an attribute like petName, pass props instead, adding a prefix where necessary (eg, props.petName).
  7. 🐞 Minified React error #130

      The URL for this minified error (https://reactjs.org/docs/error-decoder.html?invariant=130....) leads to an error page that says Element type is invalid: expected a string ... or a class/function ... but got: object.. This is usually the same problem as Module not defined.

  8. 🐞 Minified React error #152 (missing content)

      The URL for this minified error (https://reactjs.org/docs/error-decoder.html/?invariant=152...) leads an error page that says Nothing was returned from render.

    • Add a missing return statement around your JSX, eg:
    • 
      const Card = () => {
      	return (
          	<View>
            		<Text>
      				...
      	)
      }
      
    • If you really want to return nothing, return null.
    • 
      const EmptyCard = () => {
      	return null
      }
      
  9. 🐞 Minified React error #301

      The URL for this minified error (https://reactjs.org/docs/error-decoder.html/?invariant=301...) leads to an error page that says Too many re-renders. This error means React is stopping you from creating an infinite loop by re-rendering a condition over and over.

    • Change a state variable from being always true to being conditionally true.
    • 
      const [ isLoggedIn, setIsLoggedIn ] = useState(false) ; // This sets an initial state.
      // This is always true and will re-render the screen endlessly.
      setIsLoggedIn( true ); ❌
      // This only re-renders once the user has logged in.
      if ( password === "girlboss" ) { setIsLoggedIn( true ) } ; ✅
      
  10. 🐞 Invariant Violation: Text strings must be rendered within a <Text> component

      Although this error doesn't always come with a line number, the problem is likely inside a return(...) statement.

    • Remove JavaScript punctuation inside JSX, eg:
    • 
      // Bad.
      return(
      	...
      ;)
      // Good.
      return(
      	...
      );
      
    • Remove a JavaScript expression inside JSX that resolves to a string, eg
    • 
      <View>{ "I'm not supposed to be here!" }</View>
      
    • Use a ternary (?) instead of an AND (&&) conditional.
    • 
      age > 18 && <AdultContent /> ❌
      age > 18 ? <AdultContent /> : null ✅
      
  11. 🐞 Your app hangs and you can't click on anything

      You could be triggering too many refreshes with useEffect

    • Use the technique shown in this tutorial to prevent endless updates by adding a second parameter with an empty array to useEffect.
  12. 🐞 Adjacent JSX elements must be wrapped in an enclosing tag

      This message means you've returned two "sibling" tags instead of a parent to contain them. This error will be at the highest level of one of your return statements.

    • Wrap your siblings in an arbitrary tag, usually a <View>.
    • Wrap your siblings in a special JSX fragment <>...</>
    • Watch out for siblings hiding in the syntax of a ternary conditional. Only tags count, so isLoggedIn below is not a true parent.
    • 
      // This will fail ❌
      { !isLoggedIn?
      	(
      		<LoginForm />
      	) : (
      		<Text> Welcome to My Pet Finder app</Text>
      		<SubmitButton whenPressed={() => navigation.navigate('Pets')}>
      			See Your pets
      		</SubmitButton> 
      	)
      }
      // This will succeed ✅
      { !isLoggedIn?
      	(
      		<LoginForm />
      	) : (
      		<View>
      			<Text> Welcome to My Pet Finder app</Text>
      			<SubmitButton whenPressed={() => navigation.navigate('Pets')}>
      				See Your pets
      			</SubmitButton> 
      		</View>
      	)
      }
      
  13. 🐞 Component contents aren't appearing

      (eg, for a Card):

    • Check that you remembered to pass your props to your component.
    • Check for inconsistencies in your property names between the parent and child components, eg
    • 
      <Card petType = "Bulldog" />
      ...
      const Card = props => {
      	return (
      		<Text>{ props.petBreed }</Text> â˜šī¸
      	)
      }
      
  14. 🐞 package.json Failed to resolve dependency ...

      This can be a problem with the configuration code you are supposed to import at the top of your file.

    • Make sure App.js or other relevant components include the dependence (eg, import firebase from "firebase"), and that you have clicked Add the Dependency when prompted (for a Snack).
    • Also remember that the Expo platform may not have caught up with the latest version of your library. For example, for Firebase to be compatible with Expo Snacks as of spring 2023, change "firebase": "*" to "firebase": "8.0.0" in package.json, eg from this:
    • 
      {
        "dependencies": {
          "firebase": "*",
          ...
        }
      }
      
    • to this:
    • 
      {
        "dependencies": {
          "firebase": "8.0.0",
          ...
        }
      }
      
    • More generally, Google the error and restrict returns to the last year. Often someone online has figured out the latest version that still works.
    • For Firebase, also don't forget the ! when checking if Firebase already exists.
    • 
      if ( !firebase.apps.length ) firebase.initializeApp( firebaseConfiguration ) ;
      
  15. 🐞 Cannot read property 'blah' of undefined ...

      Check the button that navigates to your detail screen. If you're navigating to a component (like a detail screen) that depends on custom parameters, you'll need to pass an object containing them as a second argument to navigation.navigate.

      
      <Button onPress={ () => navigation.navigate(
      	"Pets", 
      	{
      		petName,
      		petBreed,
      		petAge
      	}
      ) }>
      

      This is necessary even if you are using the streamlined useNavigation() hook, but only when the next screen depends on data from the first.

  16. Good coding practices for React Native Back to top ↑

  17. 👍 Semicolons ; should end JavaScript statements, but not JSX. Eg, you should have a ; after your return () but not after a component tag like <View>
  18. 👍 It's much easier to find a brace {, bracket [, or parenthesis ( out of place is to indent your code carefully. Unfortunately, the "Prettier" auto-indenter won't work until you resolve that error.
  19. 👍 To make it easier to debug or style a particular component that takes a while to navigate to, you can temporarily change it to the initial screen in the navigator with <Stack.Navigator initialRouteName="Pets">.
  20. 👍 State errors: Snacks seem to get confused referring to states of two different components in the same .js file, so best to separate each component into its own .js file.
  21. 👍 To update content like <Picker> options that comes from a database, call a helper method of the component class from inside the return statement. If you try to do this outside the return, it will only fire once--potentially before the data loads, which would yield no results.
  22. General debugging strategies

  23. ⛑ When seeking help, always share the error you get. It will appear on your phone (or simulator) in a red box, or at the bottom of a Snack page, or in Terminal for Expo CLI.
  24. ⛑ If Snack's error console is not helpful, try loading the Snack in Expo Go on your phone and looking for a more specific error message there.
  25. ⛑ Another great tool is console.log( myVariable ), or in JSX { console.log( myVariable ) }. Use it to check on the state of variables, or just add it at the beginning of your code and keep moving it further down to see if it executes before the error. If it disappears at some point, that means your error occurred before the last place you moved the console.log statement.
  26. ⛑ If you get a weird error in Snack, try reloading the page. Sometimes Snack default libraries (not your files, but default ones like StyleSheet.js) don't seem to load properly.
  27. ⛑ If you aren't seeing changes you made, reload your app by shaking your phone or in the simulator by choosing the Hardware > Shake pull-down option (Control-Command-Z).
  28. ⛑ If all else fails, comment out parts of your code to find the bug. To comment out code: /* ... */ works in pure JavaScript; {/* ... */} works in JSX.