Lesson 4 of 26
Components and Hooks, the Same as React
React Native components are plain React function components using the exact hooks you already know — this lesson shows what's actually different and what genuinely isn't.
You already know how to build components. You know that a function
component takes props and returns JSX, that useState gives you state that
survives across renders, that useEffect runs side effects in response to
changes. None of that gets re-taught here, because none of it changes in
React Native. This lesson is deliberately short on new concepts and long on
"here's the one surface that's actually different."
Same hooks, same rules, different renderer
React Native doesn't have its own version of useState, useEffect,
useMemo, or any other hook. It uses React itself — the identical package
concepts, the identical rules (hooks at the top level, not inside
conditionals or loops, and so on). The only thing that differs between a
React DOM app and a React Native app is what a component's JSX ultimately
gets turned into: DOM nodes in one case, native platform views in the
other. Everything upstream of that — your component functions, your state,
your effects — is exactly the code you already write.
import { useState } from "react";
import { View, Text, Button } from "react-native";
function Counter() {
const [count, setCount] = useState(0);
return (
<View style={{ padding: 16 }}>
<Text>Count: {count}</Text>
<Button title="Increment" onPress={() => setCount(count + 1)} />
</View>
);
}
export default Counter;Look closely at what's actually different here versus a web version of the
same component: the imports come from react-native instead of being DOM
elements, View stands in for a generic container the way a div would,
and onPress replaces onClick as the event prop name on a pressable
control. The useState call, the component function shape, the JSX
syntax, and the rule that state updates trigger a re-render are all
completely unchanged from what you already know.
The genuinely RN-specific surface
The differences that do exist are about what you import and compose, not about how components or hooks work:
- You import UI primitives —
View,Text,Image, and so on — from thereact-nativepackage instead of writing DOM tags. - Some prop names differ by platform convention (
onPressvs.onClick,styletaking an object or array rather than a CSS string). - All text content must be inside a
Textcomponent — you'll cover this properly in the next part of this track, but it's worth flagging now: a bare string as a direct child of aViewis invalid, where it would be perfectly normal directly inside adivon the web.
That's genuinely the whole list for this lesson's purposes. Nothing about hooks, component composition, prop drilling, context, or any other React concept you already know changes at all.
The part of a component that has nothing to do with rendering
Here's a teaching moment worth taking seriously, not just noting in
passing: a lot of what looks like "component logic" is actually pure state
computation that has nothing to do with View, Text, or rendering at
all. Take the counter above and pull its state-transition rule out into its
own function:
type CounterAction = { type: "increment" } | { type: "decrement" } | { type: "reset" };
function counterReducer(state: number, action: CounterAction): number {
switch (action.type) {
case "increment":
return state + 1;
case "decrement":
return state - 1;
case "reset":
return 0;
default:
return state;
}
}Notice this function imports nothing from React and nothing from
react-native. It takes a number and an action, and returns a number.
That's the entire contract. It is exactly as correct, exactly as testable,
and exactly as reusable whether the component that eventually calls it
renders a <div> on the web or a <View> on a phone — the logic behind a
hook like this is identical no matter what renders it. That portability is
worth internalizing early in this track: as you meet more RN-specific UI
later on, remember that the logic underneath a component's UI is often
plain, boring, platform-agnostic JavaScript, and only the rendering layer
on top of it is platform-specific.
You can prove this to yourself by running the reducer directly, with no component and no rendering involved at all:
Every line above is plain TypeScript logic — nothing rendered, nothing native, nothing that needs a device or simulator to make sense. That's exactly why it's fair to run it right here in your browser: it behaves identically no matter what eventually calls it.
What to remember
- React Native uses the exact same React, the exact same hooks, and the exact same rules for using them as web React — nothing about useState, useEffect, or any other hook changes.
- The genuinely RN-specific surface is small: import UI primitives from react-native, some prop names differ (onPress vs. onClick), and all text must live inside a Text component.
- State-transition logic (like a reducer function) is plain JavaScript/TypeScript with no dependency on rendering — it works identically whether a DOM component or a native component eventually calls it.
- This is why this lesson's Playground example runs a plain reducer function with console.log, rather than attempting to render View or Text — those genuinely can't run in a browser sandbox, but this logic genuinely can.
Check yourself
3 questions · pass 3/3 to unlock The Core Components: View, Text, and Image
1.How does useState behave differently in a React Native component compared to a React web component?
2.What is the correct way to render text content in a React Native component?
3.Why is it useful to extract a piece of state-transition logic (like a counter's increment/decrement rules) into a plain function separate from the component that uses it?
3 left to answer