0Pricing
React Native Academy · บทเรียน

useRef สำหรับโหนด DOM และค่าที่เปลี่ยนแปลงได้

ใช้ useRef เก็บการอ้างอิงไปยัง TextInput และสั่งโฟกัสด้วยโปรแกรม พร้อมจัดเก็บค่าที่เปลี่ยนแปลงได้ซึ่งคงอยู่ข้ามการเรนเดอร์โดยไม่ทำให้เกิดการเรนเดอร์ใหม่

useRef สำหรับโหนด DOM และค่าที่เปลี่ยนแปลงได้ เป็นบทเรียน React Native Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน React Native Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส React Native Academy มีบทเรียนทั้งหมด 4 บทเรียน

บางส่วนของบทเรียนนี้ยังไม่ได้รับการแปล และแสดงเป็นภาษาอังกฤษ

What is useRef?

useRef is a React hook that returns a mutable ref object whose .current property persists across renders. Unlike state variables, updating ref.current does not trigger a re-render. This makes useRef perfect for storing values that change frequently but should not cause the component to update.

import { useRef } from 'react';

function MyComponent() {
  const myRef = useRef(null);
  // myRef.current starts as null
  // myRef.current persists across re-renders without triggering them
}

Attaching a Ref to a Native Component

Pass a ref to a native component via its ref prop. React Native then populates ref.current with the underlying native component instance. This gives you access to methods like focus(), blur(), and measure() that are defined on the native component.

import { TextInput, Button, View } from 'react-native';
import { useRef } from 'react';

function SearchForm() {
  const inputRef = useRef(null);

  return (
    <View>
      <TextInput ref={inputRef} placeholder='Search...' />
      <Button
        title='Focus Input'
        onPress={() => inputRef.current?.focus()}
      />
    </View>
  );
}

Programmatically Focusing a TextInput

A common use case is automatically focusing the next input when the user presses Return on the keyboard. Attach refs to each TextInput and in the onSubmitEditing handler of the first input, call secondInputRef.current.focus(). This creates a smooth form keyboard flow on mobile.

function LoginForm() {
  const emailRef = useRef(null);
  const passwordRef = useRef(null);

  return (
    <View>
      <TextInput
        ref={emailRef}
        placeholder='Email'
        returnKeyType='next'
        onSubmitEditing={() => passwordRef.current?.focus()}
      />
      <TextInput
        ref={passwordRef}
        placeholder='Password'
        returnKeyType='done'
        secureTextEntry
      />
    </View>
  );
}

useRef for Mutable Values

The second major use of useRef is storing mutable values that should not trigger re-renders. Store a timer ID, an animation frame handle, a previous prop value, or any other value that changes frequently. Reading or writing ref.current is synchronous and has no render cost.

function Timer() {
  const intervalRef = useRef(null);

  const start = () => {
    intervalRef.current = setInterval(() => {
      console.log('tick');
    }, 1000);
  };

  const stop = () => {
    clearInterval(intervalRef.current);
  };

  return <Button title='Start' onPress={start} />;
}

Storing Previous State Values

A useful pattern is storing the previous value of a prop or state variable using a ref. In a useEffect that runs after every render, copy the current value into the ref. During the next render, prevRef.current holds the value from the previous render cycle, allowing you to compare old and new values.

function Counter({ count }) {
  const prevCountRef = useRef(null);

  useEffect(() => {
    prevCountRef.current = count;
  });

  const prevCount = prevCountRef.current;

  return (
    <Text>
      Now: {count} — Before: {prevCount}
    </Text>
  );
}

Avoiding Stale Closures with Refs

Event handlers and callbacks that are set up once (e.g., inside a timer or event listener) can capture a stale version of state. Store the latest value in a ref and read from the ref inside the callback to always access the most recent value, even if the callback was created many renders ago.

function MessageHandler({ onMessage }) {
  const onMessageRef = useRef(onMessage);

  useEffect(() => {
    onMessageRef.current = onMessage; // always up to date
  }, [onMessage]);

  useEffect(() => {
    const subscription = subscribe((msg) => {
      onMessageRef.current(msg); // uses latest callback
    });
    return () => subscription.unsubscribe();
  }, []); // only runs once
}

The Difference Between useRef and useState

The key difference: useState triggers a re-render when updated; useRef does not. Use useState when the value must be visible in the UI. Use useRef when the value is used for logic or side effects but its change should not cause the component to repaint. Choosing the wrong one leads to either missed UI updates or unnecessary re-renders.

// Triggers re-render — shows updated value on screen
const [count, setCount] = useState(0);

// No re-render — silent counter for internal use only
const renderCount = useRef(0);
renderCount.current += 1;

useRef with FlatList

Attaching a ref to a FlatList gives you access to imperative methods like scrollToIndex, scrollToOffset, and scrollToEnd. This is used for back-to-top buttons, alphabetic index navigation, or auto-scrolling to a newly added item at the bottom of the list.

function MessageList({ messages }) {
  const listRef = useRef(null);

  useEffect(() => {
    // Scroll to bottom when new message arrives
    listRef.current?.scrollToEnd({ animated: true });
  }, [messages.length]);

  return (
    <FlatList
      ref={listRef}
      data={messages}
      renderItem={({ item }) => <Text>{item.text}</Text>}
      keyExtractor={(item) => item.id}
    />
  );
}

Measuring a Component's Layout

Call ref.current.measure(callback) to read a component's position and size relative to the window. The callback receives x, y, width, height, pageX, and pageY. This is useful for positioning tooltips, popovers, or custom dropdown menus relative to the component that triggered them.

const buttonRef = useRef(null);

const showTooltip = () => {
  buttonRef.current?.measure((x, y, width, height, pageX, pageY) => {
    setTooltipPosition({ top: pageY + height, left: pageX });
    setTooltipVisible(true);
  });
};

<TouchableOpacity ref={buttonRef} onPress={showTooltip}>

Forwarding Refs to Custom Components

If you want to attach a ref to a custom component (not a built-in like TextInput), wrap it with React.forwardRef. The wrapper passes the ref down to the underlying native element. Without forwardRef, the ref would point to the custom component's host object, not its inner TextInput.

const CustomInput = React.forwardRef((props, ref) => (
  <TextInput
    ref={ref}
    style={styles.customInput}
    {...props}
  />
));

// Now you can use the ref on CustomInput
const inputRef = useRef(null);
<CustomInput ref={inputRef} />

useRef Initialization and Lazy Init

The argument passed to useRef(initialValue) sets ref.current only on the first render — just like useState's initial value. Unlike useState, there is no lazy initializer function form. If the initial value is expensive to compute, compute it conditionally: if (ref.current === null) ref.current = computeValue().

const cacheRef = useRef(null);

if (cacheRef.current === null) {
  // Expensive computation runs only once
  cacheRef.current = buildLargeDataStructure();
}

// Use cacheRef.current anywhere in the component

Quick Check

Test your understanding of the useRef hook from this lesson.

Lesson Recap

In this lesson you learned: useRef provides a mutable .current property that persists across renders without causing re-renders, attach refs to native components to call imperative methods like focus(), and store timer IDs, previous values, and stable callbacks in refs to avoid stale closures. Next up we explore useReducer for managing complex state logic.

คำถามที่พบบ่อย

บทเรียน “useRef สำหรับโหนด DOM และค่าที่เปลี่ยนแปลงได้” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “useRef สำหรับโหนด DOM และค่าที่เปลี่ยนแปลงได้” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส React Native Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส React Native Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “useRef สำหรับโหนด DOM และค่าที่เปลี่ยนแปลงได้”

ใช้ useRef เก็บการอ้างอิงไปยัง TextInput และสั่งโฟกัสด้วยโปรแกรม พร้อมจัดเก็บค่าที่เปลี่ยนแปลงได้ซึ่งคงอยู่ข้ามการเรนเดอร์โดยไม่ทำให้เกิดการเรนเดอร์ใหม่ คุณปฏิบัติ React Native Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน React Native Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน React Native Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “useRef สำหรับโหนด DOM และค่าที่เปลี่ยนแปลงได้” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน React Native Academy นี้ได้ไหม

ได้ บทเรียน React Native Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. useRef สำหรับโหนด DOM และค่าที่เปลี่ยนแปลงได้
  2. useReducer สำหรับตรรกะสถานะที่ซับซ้อน
  3. useCallback และ useMemo เพื่อประสิทธิภาพ
  4. การเขียนฮุกแบบกำหนดเอง
← กลับไปที่ React Native Academy