Open aboodman opened 2 years ago
This would be much appreciated. If the example used expo that would be a win, https://docs.expo.dev/versions/latest/sdk/sqlite/.
This is currently being addressed well by https://github.com/Braden1996/react-native-replicache, but we should consider making it first-class.
This is currently being addressed well by https://github.com/Braden1996/react-native-replicache
@aboodman I've been recently trying to go that way but unfortunately replicache@14
(maybe even from v13) does not work in react native at all.
replicache
dependencies like @rocicorp/logger
(can probably be solved with unstable package exports support).replicache
now uses EventTarget
which is not available in react nativeAlso, react-native-replicache
doesn't seem to work with expo-sqlite@11
because the native module gets imported with the wrong key from the native modules proxy. It doesn't seem maintained at all tbh.
Can you share any plans for an official and reliable solution?
Edit: I just tested with replicache@13
, I get ReferenceError: Property 'BroadcastChannel' doesn't exist
.
Ah, I did not know that react-native-replicache had stopped working. Thanks for the information.
Ah, I did not know that react-native-replicache had stopped working. Thanks for the information.
@aboodman It's not just react-native-replicache
, actually the problems with that library are easily solvable, the real problems are with the replicache
library, which doesn't work in a react native environment anymore because of the use of browser-only APIs like BroadcastChannel
and EventTarget
.
I'd really like to use Replicache in my mobile apps (I think that's where local-first apps really shine), but these problems related to browser-only APIs make me think that react native support is not even being considered, which is fair but it'd be great to know that before committing to anything.
Would you mind sharing your team's plans about this, if any?
Thanks @darioielardi.
So we fixed the BroadcastChannel
dependency in Replicache 14:
This wasn't for React Native, but older Safaris. Unfortunately, we introduced the EventTarget
dep at same time:
The real issue here is that we don't have a RN sample, and thus aren't testing RN as part of our release process. I agree you should not rely on RN for anything real if we're not doing that.
I do not have a concrete timeline for this right now other than 2024. I'll have a better idea in January.
@aboodman that makes sense, I'll look forward to any updates on official React Native support and take some other route in the meantime, thank you!
wanted to post some updates here as we just completed a successful upgrade to replicache 14 on react-native. here are the workarounds to everything we ran into:
there's a polyfill for EventTarget (thanks to @aboodman for pointing us toward it) https://www.npmjs.com/package/event-target-polyfill - just add this to your dependencies, and add an import to your project root (in index.js)
there were a couple of changes to our babel config that were tricky to figure out. here's our config:
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
'@babel/plugin-transform-flow-strip-types',
'react-native-reanimated/plugin',
['@babel/plugin-transform-private-methods', { loose: true }],
],
};
['@babel/plugin-transform-private-methods', { loose: true }]
was required by something in the replicache module. however, this broke react-native flatlists in our jest tests. '@babel/plugin-transform-flow-strip-types',
was the solution for that.
patch-package
to fix the @rocicorp dependencies for the replicache module. They've been bundled in such a way where the output file is in a out
folder, but the package.json is missing a main
delcaration, so the bundler gets confused. you can use patch-package
with the --exclude
flag like so:
npx patch-package --exclude '^$' @rocicorp/resolver
to add main
to each of the sub-packages package.json (resolver, logger, and lock)
ex: "main": "./out/logger.js",
also, react-native-replicache
is still working for us (thankfully) but we are NOT using expo, so YMMV.
hope all of this this helps somebody!
@robsoden thank you very much! Inspired by your comment I went ahead and tried to make it work again, this time with @react-native-replicache/react-native-quick-sqlite
.
I successfully setup babel and patched all the packages, but I'm still getting errors with @react-native-replicache/react-native-quick-sqlite
:
react-native-quick-sqlite@8.0.0-beta.2
I'm getting Quick SQLite Error: Cannot execute query on finalized transaction
.react-native-quick-sqlite@8.0.4
and @react-native-replicache/react-native-quick-sqlite
patched based on this PR I get Error: unable to open database file
.Do you mind sharing your setup? Or at least what version of these libraries you are using?
@darioielardi glad it was helpful!
so I'm using the following:
"@react-native-replicache/react-native-quick-sqlite": "^1.0.0"
"react-native-quick-sqlite": "^8.0.4"
and then I've used patch-package to apply those 2 changes to the ReplicacheQuickSQLiteTransaction class (since my PR you found hasn't been merged yet)
the generated patch ends up looking like this:
diff --git a/node_modules/@react-native-replicache/react-native-quick-sqlite/src/replicache-quick-sqlite-transaction.ts b/node_modules/@react-native-replicache/react-native-quick-sqlite/src/replicache-quick-sqlite-transaction.ts
index a86aaa7..710f9a9 100644
--- a/node_modules/@react-native-replicache/react-native-quick-sqlite/src/replicache-quick-sqlite-transaction.ts
+++ b/node_modules/@react-native-replicache/react-native-quick-sqlite/src/replicache-quick-sqlite-transaction.ts
@@ -2,7 +2,7 @@ import { ReplicacheGenericSQLiteTransaction } from "@react-native-replicache/rep
import * as QuickSQLite from "react-native-quick-sqlite";
export class ReplicacheQuickSQLiteTransaction extends ReplicacheGenericSQLiteTransaction {
- private _tx: QuickSQLite.TransactionAsync | null = null;
+ private _tx: QuickSQLite.Transaction | null = null;
private _transactionCommittedSubscriptions = new Set<() => void>();
private _txCommitted = false;
private _transactionEndedSubscriptions = new Set<{
@@ -20,7 +20,7 @@ export class ReplicacheQuickSQLiteTransaction extends ReplicacheGenericSQLiteTra
return await new Promise<void>((resolve, reject) => {
let didResolve = false;
try {
- this.db.transactionAsync(async (tx) => {
+ this.db.transaction(async (tx) => {
didResolve = true;
this._tx = tx;
resolve();
let me know if there's any other info that might help
oh and also FWIW here's my replicache instantiation, nothing really unique here:
const replicache = new Replicache<MutatorsTypeDef>({
licenseKey: Config.REPLICACHE_LICENSE_KEY ?? '',
experimentalCreateKVStore:
createReplicacheReactNativeQuickSQLiteExperimentalCreateKVStore,
name: 'your-project',
mutators,
pullInterval: null,
puller: customPuller,
pusher: customPusher,
indexes: {
...
},
pushDelay: 5000,
});
If anyone here is interested in contracting for Rocicorp to get this cleaned up, I would pay for it. I want to (a) fix Replicache to install cleanly in rn and expo, (b) if there are any automated unit style tests we can add to avoid regressions do that, (c) have a working sample of todo thst works in in rn and expo with instructions on how to set up and run that any react (web) dev can successfully follow to test and debug changes.
If you’re interested dm me on discord.replicache.dev.
@robsoden I realized the reason it wasn't working is that I was using user/userId
as the client name, which is not a valid filename for the SQLite db 🤦♂️
Everything works now! I think I'll try to make it work with expo-sqlite
and post any updates here. Thanks again for all your support!
@aboodman apparently on your side the only necessary change is to add the "main"
field to every packages.json
, 4 out of 5 patches I have are for that (all @rocicorp/
packages and replicache-react
).
About the EventTarget
polyfill, I guess it can be addressed with a recommendation in the docs.
Anyone else working with Repliache and react-native may have also noticed that react-native-quick-sqlite has recently been deprecated, with the maintainer suggesting a migration to op-sqlite (https://github.com/ospfranco/react-native-quick-sqlite)
quick-sqlite was the main underlying store implemented by the (very excellent) react-native-replicache package (https://github.com/Braden1996/react-native-replicache)
Luckily, thanks to the very solid work on that package, it was pretty trivial to swap in op-sqlite. I've submitted a PR there in the hopes that they'll publish a new adapter.
Feel free to reach out if anyone needs this and has trouble implementing. If there's no movement on the PR over there, we may just publish it ourselves depending on outside interest.
Thanks!
Anyone else working with Repliache and react-native may have also noticed that react-native-quick-sqlite has recently been deprecated, with the maintainer suggesting a migration to op-sqlite (https://github.com/ospfranco/react-native-quick-sqlite)
quick-sqlite was the main underlying store implemented by the (very excellent) react-native-replicache package (https://github.com/Braden1996/react-native-replicache)
Luckily, thanks to the very solid work on that package, it was pretty trivial to swap in op-sqlite. I've submitted a PR there in the hopes that they'll publish a new adapter.
Feel free to reach out if anyone needs this and has trouble implementing. If there's no movement on the PR over there, we may just publish it ourselves depending on outside interest.
Thanks!
Ran into the same issues and your fixes worked like a charm. Thank you!
I've pinged the owner of https://github.com/Braden1996/react-native-replicache and he said he'll have a look at the open PRs tomorrow.
Hello all!
Over the weekend I upgraded the React Native Replicache libraries in a few ways. Sorry for not being better with this.
It is worth noting:
op-sqlite
and expo-sqlite
bindings.
@aboodman as for an example app you can add to your test flow, the example provided in that repo should work pretty well and I've added some instructions to the Readme. More than happy to hop on a call and go through it!
Also, regarding EventTarget
being introduced, I would suggest removing dom
from your internal repo's TSConfig lib
. The TS ecosystem has a habit of sticking this in everywhere. We recently removed it from all unnecessary packages at Attio (basically by introduce a "universal types" package which defined the client APIs we expect to be available on all runtimes, like setTimeout
).
Also, regarding
EventTarget
being introduced, I would suggest removingdom
from your internal repo's TSConfiglib
. The TS ecosystem has a habit of sticking this in everywhere. We recently removed it from all unnecessary packages at Attio (basically by introduce a "universal types" package which defined the client APIs we expect to be available on all runtimes, likesetTimeout
).
I would love to do this. It has been a pet peeve of mine for the last year at least. We do have a lot of bindings (through IDB and fetch) so we need to maintain a copy of those entire type hierarchies. Is your "universal types" package available?
Also, regarding
EventTarget
being introduced, I would suggest removingdom
from your internal repo's TSConfiglib
. The TS ecosystem has a habit of sticking this in everywhere. We recently removed it from all unnecessary packages at Attio (basically by introduce a "universal types" package which defined the client APIs we expect to be available on all runtimes, likesetTimeout
).I would love to do this. It has been a pet peeve of mine for the last year at least. We do have a lot of bindings (through IDB and fetch) so we need to maintain a copy of those entire type hierarchies. Is your "universal types" package available?
We don't plan on publishing it, unfortunately.
Although it's pretty straightforward: mostly a rip of React Native's global types, which you can find here: https://www.npmjs.com/package/react-native?activeTab=code under /react-native/types/modules/globals.d.ts
I'd very much like to use Replicache in an Expo (v51) project. Wondering if this is advisable or if I should hold off for now?
Currently it is possible to use Replicache with React Native by implementing
experimentalKVStore
and hooking it to SQLite. However it's quite manual. We should have first-class support for RN, including: