You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tauri v2 + Next.js v15环境下useDatabase钩子中window.__TAURI__未定义,无法加载SQLite数据库单例

Tauri v2 + Next.js v15环境下useDatabase钩子中window.__TAURI__未定义,无法加载SQLite数据库单例

遇到这个问题很常见,主要是Next.js的SSR特性和Tauri环境的特殊性导致的,我来帮你一步步解决:

问题根源分析

  • Next.js SSR的影响:Next.js默认是服务器端渲染,组件在服务器端执行时,window对象根本不存在,更别说window.__TAURI__了——这个全局变量只有在Tauri客户端运行时才会注入。
  • 不必要的全局变量依赖:Tauri v2的插件API已经封装了环境检测,你不需要手动去判断window.__TAURI__,直接调用插件提供的方法即可。
  • 单例实现方式问题:用useState存储数据库实例可能会导致重复初始化,应该用useRef来保持单例引用,避免多次加载数据库。

解决方案步骤

1. 标记组件为客户端组件(Next.js App Router)

因为Tauri的API只能在客户端环境运行,所以你的钩子文件需要加上'use client'指令,告诉Next.js这个组件只在客户端执行:

'use client'; // 必须加在文件最顶部
import { useState, useEffect, useRef } from 'react';
import Database from '@tauri-apps/plugin-sql';

type DatabaseInstance = Awaited<ReturnType<typeof Database.load>>;

2. 修正useDatabase钩子,实现真正的单例

用useRef存储数据库实例,确保只初始化一次,同时避免SSR阶段的错误:

export const useDatabase = () => {
    const [db, setDb] = useState<DatabaseInstance | null>(null);
    const isInitialized = useRef(false); // 标记是否已经初始化过

    useEffect(() => {
        // 避免重复初始化
        if (isInitialized.current) return;
        isInitialized.current = true;

        // 直接调用Database.load,插件会自动处理环境检测
        const initDatabase = async () => {
            try {
                const database = await Database.load('sqlite:test.db');
                console.log('Database loaded successfully:', database);
                setDb(database);
            } catch (error) {
                console.error('Failed to load database:', error);
            }
        };

        initDatabase();
    }, []);

    return db;
};

3. 移除自定义的window类型声明

你不需要手动声明window.__TAURI__的类型,@tauri-apps/plugin-sql已经提供了完整的类型定义,直接删除你写的那个全局类型文件即可,避免类型冲突。

4. 确保依赖版本匹配

检查你的package.json中Tauri相关依赖的版本是否一致,比如@tauri-apps/cli和@tauri-apps/plugin-sql的主版本号要保持一致(都是2.x),目前你的版本是匹配的,这点没问题。

额外注意事项

  • 不要在普通浏览器中测试:window.__TAURI__只有在Tauri客户端(即npm run tauri dev启动的窗口)中才会存在,普通浏览器打开Next.js的开发服务(比如npm run dev)肯定会找不到这个变量,这是正常的。
  • 如果使用Page Router:如果你的项目是Next.js Page Router,那么可以用dynamic导入你的组件,禁用SSR:
    import dynamic from 'next/dynamic';
    
    const DatabaseComponent = dynamic(() => import('./DatabaseComponent'), { ssr: false });
    

这样修改后,你的数据库单例应该就能正常工作了,不会再出现window.__TAURI__未定义的错误。

备注:内容来源于stack exchange,提问作者SacredDoggo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 09:08:11