WatermelonDB: Complete Setup Guide for React Native Expo

Table Of Content
- Getting Started with WatermelonDB
- Installation Steps
- Install core and required dependenciesnpx expo install @nozbe/watermelondbnpx expo install @nozbe/watermelondb/adapters/sqlitenpx expo install react-native-quick-sqlite# Install dev dependencies for buildingnpm install --save-dev @babel/plugin-proposal-decorators
- Babel Configuration
- Database Setup
- 1. Create Database Configuration
- 2. Define Your Schema
- 3. Create Models
- 4. Set up Provider
- Using WatermelonDB
- Creating Records
- Querying Records
- Best Practices
- Common Issues and Solutions
- 1. Schema Migration
- 2. Performance Optimization
- Conclusion
WatermelonDB is a high-performance reactive database for React Native that helps you build powerful offline-first applications. This guide will walk you through the complete setup process in a React Native Expo project.
Getting Started with WatermelonDB
Installation Steps
First, let's install all the necessary dependencies. Open your terminal and run:
# Install core and required dependenciesnpx expo install @nozbe/watermelondbnpx expo install @nozbe/watermelondb/adapters/sqlitenpx expo install react-native-quick-sqlite# Install dev dependencies for buildingnpm install --save-dev @babel/plugin-proposal-decorators
Babel Configuration
Create or modify your babel.config.js
file to include the necessary plugins:
module.exports = function (api) { api.cache(true); return { presets: ['babel-preset-expo'], plugins: [ ['@babel/plugin-proposal-decorators', { legacy: true }], ], };};
Database Setup
1. Create Database Configuration
Create a new file database/index.js
:
import { Database } from '@nozbe/watermelondb'import SQLiteAdapter from '@nozbe/watermelondb/adapters/sqlite'import { schemas } from './schema'import { models } from './models'const adapter = new SQLiteAdapter({ schema: schemas,})export const database = new Database({ adapter, modelClasses: models,})
2. Define Your Schema
Create database/schema.js
:
import { appSchema, tableSchema } from '@nozbe/watermelondb'export const schemas = appSchema({ version: 1, tables: [ tableSchema({ name: 'posts', columns: [ { name: 'title', type: 'string' }, { name: 'body', type: 'string' }, { name: 'created_at', type: 'number' }, ] }) ]})
3. Create Models
Create database/models/Post.js
:
import { Model } from '@nozbe/watermelondb'import { field, date } from '@nozbe/watermelondb/decorators'export class Post extends Model { static table = 'posts' @field('title') title @field('body') body @date('created_at') createdAt}
4. Set up Provider
In your App.js
:
import { DatabaseProvider } from '@nozbe/watermelondb/DatabaseProvider'import { database } from './database'export default function App() { return ( <DatabaseProvider database={database}> {/* Your app content */} </DatabaseProvider> )}
Using WatermelonDB
Creating Records
import { useDatabase } from '@nozbe/watermelondb/hooks'function CreatePost() { const database = useDatabase() const createPost = async () => { await database.write(async () => { await database.get('posts').create((post) => { post.title = 'My First Post' post.body = 'Hello WatermelonDB!' }) }) } return ( <Button onPress={createPost} title="Create Post" /> )}
Querying Records
import { withDatabase } from '@nozbe/watermelondb/DatabaseProvider'import withObservables from '@nozbe/with-observables'function PostsList({ posts }) { return ( <FlatList data={posts} renderItem={({ item }) => ( <Text>{item.title}</Text> )} /> )}const enhance = withObservables([], ({ database }) => ({ posts: database.get('posts').query().observe()}))export default withDatabase(enhance(PostsList))
Best Practices
- Batch Operations: Use batch operations when performing multiple writes:
await database.write(async () => { await database.batch( database.get('posts').prepareCreate(post => { post.title = 'Post 1' }), database.get('posts').prepareCreate(post => { post.title = 'Post 2' }) )})
- Error Handling: Always wrap database operations in try-catch blocks:
try { await database.write(async () => { // database operations })} catch (error) { console.error('Database operation failed:', error)}
- Relationships: Define relationships between models using associations:
import { associations } from '@nozbe/watermelondb/Model'class Post extends Model { static associations = associations([ 'comments', 'author', ])}
Common Issues and Solutions
1. Schema Migration
When updating your schema, create migrations:
import { schemaMigrations } from '@nozbe/watermelondb/Schema/migrations'const migrations = schemaMigrations({ migrations: [ { toVersion: 2, steps: [ // Migration steps ], }, ],})
2. Performance Optimization
- Use
lazy.load()
for large relationships - Implement pagination using
query().limit(20)
- Use appropriate indexes in your schema
Conclusion
WatermelonDB is a powerful tool for building offline-first applications in React Native. By following this setup guide, you've learned how to:
- Install and configure WatermelonDB
- Set up your database schema and models
- Perform basic CRUD operations
- Handle relationships and migrations
- Implement best practices for optimal performance
Remember to always refer to the official documentation for more detailed information and advanced features.
For more information about using WatermelonDB with TypeScript, advanced queries, or specific use cases, feel free to check out the official documentation or reach out to the community.