From Web to Mobile: Sharing Logic
Maintaining two separate codebases for Web (Next.js) and Mobile (React Native) is painful when they share the same business logic.
The Problem I Faced
I had a Next.js website and an Expo app. Every time I updated the user validation logic or the API client in one, I had to copy-paste it to the other. Mistakes happened, and bugs appeared in one platform but not the other.
The Solution: Shared Packages
Even without a complex Monorepo tool like Nx or Turborepo, you can structure your logic to be platform-agnostic.
Code Example 1: Platform-Agnostic Hook
This hook works perfectly in both Next.js and React Native because it relies on standard React hooks and standard fetch/Axios, not DOM elements.
// hooks/useUser.ts
import { useState, useEffect } from 'react';
import { apiClient } from '../api/client';
export const useUser = (userId: string) => {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
apiClient.get(`/users/${userId}`)
.then(res => setUser(res.data))
.finally(() => setLoading(false));
}, [userId]);
return { user, loading };
};Code Example 2: Shared Zod Schema
// shared/schema.ts
import { z } from 'zod';
// This runs anywhere JS runs
export const loginSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
});Common Pitfalls
- Mistake 1: Importing platform-specific code in shared files.
- Don't: Import
<div>orViewin your business logic files. - Do: Keep shared files pure TypeScript or generic React hooks.
- Don't: Import
Pro Tips
- API Client: Create a singleton API client (Axios instance) that handles auth tokens, so your hooks remain clean.
- Types: Share your TypeScript interfaces (or Zod inferences) so your frontend and mobile app assume the same API shape.
Wrapping Up
Start small by sharing types and constants. Eventually, move your intricate business logic hooks into a shared folder. Your future self will thank you for the DRY code.
Tech Stack: Next.js, React Native, TypeScript
