All skills

Complete React Native and Expo optimization guide combining Callstack profiling with Vercel code patterns. Covers FPS, TTI, bundle size, memory, lists, animations, state, UI, and React Compiler. Use for any React Native performance, debugging, or best practices task.

Use this Skill: https://skilld.dev/gh/gigs-slc/react-native-skills/react-native

This session only. Nothing lands on disk.

rulesreact-state-dispatcher.md

≈564 tokens on demand. Your agent reads this file only when SKILL.md points to it.

Use Dispatch Updaters for State That Depends on Current Value

When the next state depends on the current state, use a dispatch updater (setState(prev => ...)) instead of reading the state variable directly in a callback. This avoids stale closures and ensures you're comparing against the latest value.

Incorrect (reads state directly):

const [size, setSize] = useState<Size | undefined>(undefined)

const onLayout = (e: LayoutChangeEvent) => {
  const { width, height } = e.nativeEvent.layout
  // size may be stale in this closure
  if (size?.width !== width || size?.height !== height) {
    setSize({ width, height })
  }
}

Correct (dispatch updater):

const [size, setSize] = useState<Size | undefined>(undefined)

const onLayout = (e: LayoutChangeEvent) => {
  const { width, height } = e.nativeEvent.layout
  setSize((prev) => {
    if (prev?.width === width && prev?.height === height) return prev
    return { width, height }
  })
}

Returning the previous value from the updater skips the re-render.

For primitive states, you don't need to compare values before firing a re-render.

Incorrect (unnecessary comparison for primitive state):

const [size, setSize] = useState<Size | undefined>(undefined)

const onLayout = (e: LayoutChangeEvent) => {
  const { width, height } = e.nativeEvent.layout
  setSize((prev) => (prev === width ? prev : width))
}

Correct (sets primitive state directly):

const [size, setSize] = useState<Size | undefined>(undefined)

const onLayout = (e: LayoutChangeEvent) => {
  const { width, height } = e.nativeEvent.layout
  setSize(width)
}

However, if the next state depends on the current state, you should still use a dispatch updater.

Incorrect (reads state directly from the callback):

const [count, setCount] = useState(0)

const onTap = () => {
  setCount(count + 1)
}

Correct (dispatch updater):

const [count, setCount] = useState(0)

const onTap = () => {
  setCount((prev) => prev + 1)
}

Source: SKILL.md on GitHub

2 alerts6mo4 checks · Risk HIGH
  • Gen Agent Trust Hub7mo

    The skill is a technical React Native guide that includes a high-risk remote code execution pattern for installing a performance tool.

  • Socket6mo

    No alerts

  • Snyk7mo

    Risk: MEDIUM · No issues

  • Runlayer7mo

    7/67 files flagged

Signed by skilld at 1d299ca. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 days ago.

Dormantupdated 8 months ago
Other metadata
metadata
{
  "author": "Callstack + Vercel",
  "version": "1.0.0",
  "tags": "react-native, expo, performance, optimization, patterns"
}

README badge

README badge for gigs-slc/react-native-skills/react-native