Skip to content

Instantly share code, notes, and snippets.

View SwarajDashDev's full-sized avatar

Swaraj Dash SwarajDashDev

View GitHub Profile
@SwarajDashDev
SwarajDashDev / hermes-vs-jsc.md
Created March 18, 2026 04:47
A quick look at why Hermes often outperforms JavaScriptCore in React Native apps and how to switch engines with minimal friction.

Insight

React Native ships with two JavaScript engines: the default JavaScriptCore (JSC) on iOS and Android, and the optional Hermes engine. Hermes compiles JavaScript to bytecode ahead‑of‑time, which reduces startup time, memory footprint, and improves overall frame rates—especially on low‑end Android devices. JSC still offers broader compatibility (e.g., newer ES features) but can be slower to parse large bundles. The trade‑off is usually worth it for production apps that target a wide Android audience, while iOS developers often stay on JSC because Hermes support is newer and may require extra testing.

Example

// app.json (or expo-config.ts)
{
  "expo": {
    "jsEngine": "hermes",
 "android": { "enableHermes": true },
@SwarajDashDev
SwarajDashDev / mmkv-vs-asyncstorage-performance.md
Created March 19, 2026 10:12
A quick comparison of MMKV and AsyncStorage, showing why MMKV can dramatically speed up key‑value storage in React Native apps.

Insight

AsyncStorage is the default key‑value store in React Native, but it serializes every read/write to JSON and hits the bridge on each operation, which can become a bottleneck in data‑heavy screens. MMKV, a native key‑value storage library from WeChat, keeps data in a memory‑mapped file and offers zero‑copy reads, making it up to 10× faster for frequent reads and writes. Switching is straightforward and brings noticeable UI smoothness, especially when persisting form state, caching API responses, or handling auth tokens.

Example

import { MMKV } from 'react-native-mmkv';

const storage = new MMKV();

export const setToken = (token: string) => storage.set('authToken', token);
@SwarajDashDev
SwarajDashDev / react-native-fast-image-caching.md
Created March 19, 2026 10:13
Leverage react-native-fast-image to cache remote assets, cut network churn, and keep scrolling buttery‑smooth on both iOS and Android.

Insight

Remote images are a hidden performance killer in React Native apps—each scroll can trigger a new HTTP request, causing jank and wasted data. react-native-fast-image replaces the default Image component with a native‑backed view that implements aggressive caching, priority loading, and automatic memory management. By declaring a cache policy per‑image you can keep frequently used assets on‑device for the app’s lifetime, dramatically reducing load times and network usage.

Example

import FastImage from 'react-native-fast-image';

export default function Avatar() {
  return (
 
@SwarajDashDev
SwarajDashDev / trim-react-native-bundle-console-removal-inline-requires.md
Created March 20, 2026 05:43
Learn how a couple of Babel tweaks—removing console statements and enabling inline requires—can shave megabytes off your RN bundle and speed up startup.

Insight

In production builds, stray console.log calls and eager module loading are silent performance killers. Each console.* line adds dead code that the JS engine still parses, while loading whole modules up front inflates the initial bundle. By stripping console statements with babel-plugin-transform-remove-console and turning on Metro's inlineRequires, you let the JavaScript engine lazily load only what’s needed, cutting bundle size and improving cold‑start times.

Example

// babel.config.js
module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
  env: {
 production: {
@SwarajDashDev
SwarajDashDev / typed-api-hooks-with-react-query.md
Created March 20, 2026 15:18
Leverage TypeScript generics to build reusable, type‑safe data‑fetching hooks with React Query, reducing boilerplate and catching API contract errors at compile time.

Insight

Creating a separate hook for every endpoint quickly becomes noisy, especially when the response shape varies. By defining a single generic useApi hook you let TypeScript infer the payload type from the function you pass in, while React Query still handles caching, retries, and background refetching. This pattern keeps your component code clean and guarantees that you only ever access fields that exist on the response.

Example

import { useQuery, UseQueryOptions } from '@tanstack/react-query';
import { fetch } from 'expo-network';

// Generic hook
function useApi(
@SwarajDashDev
SwarajDashDev / atomic-state-with-jotai.md
Created March 20, 2026 15:20
Discover how Jotai lets you manage isolated pieces of state with tiny atoms, cutting down on Redux boilerplate while keeping re‑renders predictable.

Insight

Jotai introduces atoms—tiny, independent state units that can be read or written anywhere in your component tree. Unlike Redux Toolkit or Zustand, you don't need a central store or reducers; each atom lives on its own, making it perfect for feature‑scoped state like a modal toggle or a form field. Because React only re‑renders components that subscribe to a changed atom, you get fine‑grained updates without the overhead of a global store.

Example

import { atom, useAtom } from 'jotai';

// A simple boolean atom for a loading spinner
const loadingAtom = atom(false);
@SwarajDashDev
SwarajDashDev / typed-navigation-params.md
Created March 21, 2026 08:18
Leverage TypeScript to enforce compile‑time safety for React Navigation parameters, eliminating a common source of runtime crashes.

Insight

Navigation params are often passed as loosely‑typed objects, which means a typo or missing field only surfaces at runtime. By defining a ParamList type and tying it to useNavigation or RouteProp, you get autocomplete, compile‑time checks, and clearer intent across your codebase.

Example

// navigation/types.ts
export type RootStackParamList = {
  Home: undefined;
  Details: { id: string; title: string };
};
@SwarajDashDev
SwarajDashDev / interactionmanager-smoother-ui.md
Created March 21, 2026 11:40
Learn how to use React Native's InteractionManager to postpone expensive tasks until after animations and gestures complete, keeping the UI buttery smooth.

Insight

When a screen transition or gesture is in progress, any synchronous JavaScript work can block the UI thread, causing jank. InteractionManager lets you schedule heavy calculations, data parsing, or state updates to run after all ongoing interactions finish. This pattern is especially useful for loading large JSON payloads or initializing heavy libraries right after navigation, without sacrificing frame rates.

Example

import { InteractionManager } from 'react-native';
import { useEffect, useState } from 'react';

export default function DetailScreen() {
 const [data, setData] = useState(null);
@SwarajDashDev
SwarajDashDev / eas-update-pitfalls-ota.md
Created March 23, 2026 04:45
A quick look at the hidden costs of over‑relying on Expo Application Services (EAS) OTA updates and how to mitigate version‑drift issues.

Insight

Expo's EAS Update lets you push JavaScript changes without a store review, but treating it as a universal release mechanism can backfire. OTA updates bypass native code changes, so any modification to native modules, permissions, or linked libraries will be ignored until the next binary release. This creates a silent version drift where users run a mix of old native binaries and new JS bundles, leading to crashes that are hard to reproduce.

Example

// eas.json – keep the runtime version in sync with native builds
{
  "build": {
    "development": { "runtimeVersion": "1.2.0" },
 "production": { "runtimeVersion": "1.2.0" }
@SwarajDashDev
SwarajDashDev / jsi-native-modules-performance.md
Created March 23, 2026 06:36
Learn how the JavaScript Interface (JSI) lets you call native code without the traditional React Native bridge, cutting latency and boosting UI responsiveness.

Insight

The classic React Native bridge serializes data between JavaScript and native threads, which adds noticeable latency for high‑frequency calls (e.g., animations or sensor data). JSI eliminates this overhead by exposing native objects directly to the JavaScript runtime, allowing synchronous, zero‑copy access. This is especially powerful for small utility modules or performance‑critical loops where every millisecond counts.

Example

// myModule.ts – TypeScript wrapper for a JSI‑exposed native function
import { NativeModules } from 'react-native';

// Assume the native side registers `MyJsiModule` on the JSI global object
export const MyJsiModule = {