I want to run a local-first app, so node.js is not available. I try to provide a sqljs database via context provider.
I mostly times get the error
TypeError: Cannot read properties of null (reading 'exec')
The code looks as following
SQLiteContext.js
import React, { createContext, useEffect, useState } from "react";
export const SQLiteContext = createContext();
const SQLiteProvider = ({ children }) => {
const [SQL, setSQL] = useState(null)
const [sqliteDB, setSqliteDB] = useState(null)
useEffect(() => {
initSqlJs({ locateFile: file => `/js/${file}` }).
then((aSQL)=>{
setSQL(aSQL)
setSqliteDB(new aSQL.Database())
});
}, []);
return (
<SQLiteContext.Provider value={{ SQL,setSQL ,sqliteDB,setSqliteDB }}>
{children}
</SQLiteContext.Provider>
)
}
export { SQLiteProvider };
_document.js - static html
import { Html, Head, Main, NextScript } from 'next/document'
import Script from 'next/script'
export default function Document() {
return (
<Html>
<Head />
<body>
<Script src='/js/sql-wasm.js' strategy="beforeInteractive" />
<Main />
<NextScript />
</body>
</Html>
)
}
App.js
import React, { useContext, useEffect } from "react";
import { SQLiteContext } from "../contexts/SQLiteContext";
export default function App() {
const {SQL,sqliteDB} = useContext(SQLiteContext)
const res = sqliteDB.exec("SELECT * FROM hello")
return (
<>
test
{res}
</>
)
}
index.js
import { SQLiteProvider } from "../contexts/SQLiteContext"
import App from "../components/App"
export default function Home() {
return (
<div>
<SQLiteProvider>
<App />
</SQLiteProvider>
</div>
)
}
The sqljs/initSqlJs works fine.
The Problem seems to be, that if It gets executed, it's not available yet
I tried alrady
- put all code in one file
- put the query inside the InitSqlJs(...).then((...)=>{})
- do the initSqlJs in the static.html with window.db
It seems I need to get the DB Handle before the ContextProvider, but where?