# Avoiding Re-renders and Heavy JS Work — React Native

Source: https://www.skillbyai.com/en/react-native/p-renders

> Keep the JS thread responsive.

## Why the JS thread matters

Your React code, state updates and most event handlers run on the **JavaScript thread**. If it is busy for longer than a frame (about 16 ms at 60 Hz), taps feel delayed and JS-driven animations stutter. Common causes are re-rendering large trees on every change, expensive calculations during render, and processing big JSON payloads. Remedies: keep state close to where it is used, split contexts, memoise expensive values with `useMemo`, keep callback identities stable with `useCallback` for memoised children, wrap list rows in `React.memo`, virtualise lists, paginate data and move heavy work to the server. The **React Compiler** can add memoisation automatically in supported setups; check the docs for your version. Always measure with the profiler before and after, and test performance in **release** builds, since development mode is much slower.

## Smooth at 60 frames per second

Keep the JavaScript thread free, animate off it where possible, and ship lean assets on a fast engine.

![Three ideas: rendering and JS work, animations, images, size and Hermes.](assets/figures/react-native/section-7-map.svg) — Figure 7.1 — Threads, animations and app size.

## Memoising an expensive derived value

Compute once per input change, not on every render.

```tsx
import { memo, useMemo, useState } from "react";
import { Text, TextInput, View } from "react-native";

type Tx = { id: string; amount: number; category: string };

const Summary = memo(function Summary({ total }: { total: number }) {
  return <Text>Total: {total.toFixed(2)}</Text>;
});

export function Spending({ transactions }: { transactions: Tx[] }) {
  const [note, setNote] = useState("");   // typing here should not recompute totals

  const total = useMemo(
    () => transactions.reduce((sum, t) => sum + t.amount, 0),
    [transactions],
  );

  return (
    <View>
      <Summary total={total} />
      <TextInput value={note} onChangeText={setNote} placeholder="Add a note" />
    </View>
  );
}
```

## Remove console.log in production

Many log calls with large objects slow the JS thread. Strip or gate them in release builds, for example with a Babel plugin or a logger with levels.

**Quiz:** Why can a long computation in a press handler make an app feel frozen?

- [ ] It forces the app to reinstall
- [ ] It deletes the native views
- [ ] It disables the GPU
- [x] It blocks the JavaScript thread, delaying updates and JS-driven animations

*Answer:* It blocks the JavaScript thread, delaying updates and JS-driven animations. One busy thread delays everything that depends on it.
