Sharing useState Variables in React Native with Context API and Props
Sharing useState Variables in React Native with Context API and Props

Passing State Between Files in React Native (Expo Go): How to Share useState Variables

Learn effective ways to share useState variables between React Native components using Context API and props with Expo Go.7 min


Managing state is at the core of any React Native application, particularly when developing with Expo Go. While it’s straightforward to handle state within a single component, things can get tricky once we start spreading state across multiple files. Thankfully, there’s a clear path forward for sharing those all-important useState variables between components, helping your app stay clean and organized.

Why You Might Need to Share useState Variables

When your React Native application grows beyond a single screen or component, you start noticing certain shared pieces of data become necessary. Maybe it’s a user profile, app settings, or even login state. Sharing state helps maintain consistency, saves time, and avoids bugs that result from mismatched data.

For instance, suppose you’re creating a mobile app similar to Instagram. You’d need to manage the user’s login state and share it between multiple screens like the profile page, notifications, and settings page. That’s precisely where sharing state comes in.

Using React Native’s useState hook, you can easily handle component-level states. But sometimes, that data needs to travel between files and different components to keep everything working smoothly.

Setting Up a useState Variable in React Native

The useState hook is quite straightforward. It allows us to create and manage local state within a React Native component easily.

Here’s how you might typically set up a simple useState variable to track a user’s logged-in state:

import React, { useState } from "react";
import { View, Button, Text } from "react-native";

export default function App() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  return (
    <View>
      <Text>User logged in: {isLoggedIn ? "Yes" : "No"}</Text>
      <Button
        title={isLoggedIn ? "Logout" : "Login"}
        onPress={() => setIsLoggedIn(!isLoggedIn)}
      />
    </View>
  );
}

This snippet creates a simple piece of state named isLoggedIn and sets it initially to false. Pressing the button will toggle the state between true and false.

Exporting and Importing Variables in React Native

At first glance, it might seem like exporting and importing state just like other variables would do the job. However, plain exporting of useState variables won’t function as expected, because hooks like useState must be used inside React Native components or custom hooks.

For general JavaScript variables, this pattern works:

// settings.js
export const theme = "dark";

// App.js
import { theme } from "./settings";

console.log(theme); // outputs "dark"

But attempting to apply this with useState introduces issues.

Attempting to Pass State Variables Between Files

Here’s the common pitfall developers encounter:

You set up useState in one component and then attempt something like this:

// ComponentA.js
import React, { useState } from "react";

export const [userName, setUserName] = useState("John Doe");

When importing this into another component, you’ll encounter an error, as React Native does not allow hooks like useState outside functional components or custom hooks. React hooks have specific rules—they must live inside the scope of a React function component or inside a custom hook.

This is precisely why top-level exports of hooks fail, and React Native developers hit a dead-end.

Solutions for Sharing useState Variables

Luckily, React gives us robust and simple solutions to this problem. Two common and recommended approaches are using the React Context API or passing state using props.

Method 1: Using Context API

The React Context API is one perfect technique when you have many components nested deeply, or spread over multiple files, that need the same state.

Context provides a central location for your state, accessible anywhere within the defined context provider’s tree.

Here’s how you’d implement this in React Native:

// UserContext.js
import React, { createContext, useState } from "react";

export const UserContext = createContext();

export function UserProvider({ children }) {
  const [userName, setUserName] = useState("John Doe");

  return (
    <UserContext.Provider value={{ userName, setUserName }}>
      {children}
    </UserContext.Provider>
  );
}

Then, in your main component file, you use it like this:

// App.js
import React from "react";
import { UserProvider } from "./UserContext";
import HomeScreen from "./HomeScreen";

export default function App() {
  return (
    <UserProvider>
      <HomeScreen />
    </UserProvider>
  );
}

Now, anywhere inside this component tree, components can directly access the shared state:

// HomeScreen.js
import React, { useContext } from "react";
import { View, Text } from "react-native";
import { UserContext } from "./UserContext";

export default function HomeScreen() {
  const { userName } = useContext(UserContext);
  return (
    <View>
      <Text>Welcome {userName}!</Text>
    </View>
  );
}

This approach significantly simplifies state management by reducing props drilling.

Method 2: Using Props to Pass State

Another recommended approach is to pass down state values and state-setting functions from a parent component to a child component using props instead of context.

Take a look at this simple example:

// ParentComponent.js
import React, { useState } from "react";
import ChildComponent from "./ChildComponent";

export default function ParentComponent() {
  const [count, setCount] = useState(0);

  return <ChildComponent count={count} setCount={setCount} />;
}

// ChildComponent.js
import React from "react";
import { View, Button, Text } from "react-native";

export default function ChildComponent({ count, setCount }) {
  return (
    <View>
      <Text>Current Count: {count}</Text>
      <Button title="Increment" onPress={() => setCount(count + 1)} />
    </View>
  );
}

The main takeaway: use props when state sharing is limited and context API when multiple, deeply nested components need access to the same state.

Best Practices for Passing State Between Files

Here’s a quick rundown of some best practices:

  • Use Context API: If you’ve got multiple components scattered across different screens or deeply nested components, React Context is ideal for managing shared state.
  • Avoid Excessive Props Drilling: Passing props through many middle-level components creates confusing and hard-to-maintain code structures. Use context API or state management libraries like Redux for these situations.
  • Keep Your State Simple: Don’t overcomplicate your state variables. Simple data types like primitives are easier to debug and manage.
  • Use Custom Hooks: Create custom hooks to maintain clean and modularized reusable logic, especially if the state logic becomes complex (learn more about custom hooks here).

Sharing state correctly not only keeps your application stable but also dramatically enhances readability and maintainability.

Whether through the intuitive Context API or classic prop drilling techniques, React Native equips you with multiple pathways to efficiently manage and share your state.

What method have you found most effective in your latest React Native project? Let us know your go-to state-sharing practices!


Like it? Share with your friends!

Shivateja Keerthi
Hey there! I'm Shivateja Keerthi, a full-stack developer who loves diving deep into code, fixing tricky bugs, and figuring out why things break. I mainly work with JavaScript and Python, and I enjoy sharing everything I learn - especially about debugging, troubleshooting errors, and making development smoother. If you've ever struggled with weird bugs or just want to get better at coding, you're in the right place. Through my blog, I share tips, solutions, and insights to help you code smarter and debug faster. Let’s make coding less frustrating and more fun! My LinkedIn Follow Me on X

0 Comments

Your email address will not be published. Required fields are marked *