cljsrn

https://github.com/drapanjanas/re-natal | https://github.com/drapanjanas/re-natal/wiki/FAQ | https://github.com/condense/mercury-app/wiki | https://github.com/seantempesta/expo-cljs-template/ https://www.npmjs.com/package/create-expo-cljs-app
Michael Jung 2021-05-24T11:55:30.015600Z

I’m trying to use react navigation 5 in my Krell RN app, however, I’m having difficulties loading it in my cljs files. On their “Getting started” page, they say that we have to use:

import { NavigationContainer } from '@react-navigation/native';
I’ve tried to replicate this as follows in cljs:
(ns my-app.core (:require ["@react-navigation/native" :refer [NavigationContainer]]))
But NavigationContainer just ends up being undefined/nil. If I run
(require '["@react-navigation/native" :refer [NavigationContainer]])
from the REPL, I will get
Unexpected error (IllegalArgumentException) compiling at (REPL:1).
Don't know how to create ISeq from: java.lang.Character
I’ve also tried the following:
(js/require "@react-navigation/native")
But this also returns nil. Any ideas what I am doing wrong here? For the installation of react navigation, I have followed their instructions:
npm install @react-navigation/native
npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view

dnolen 2021-05-24T12:36:11.016Z

@michael.w.jung did you check if you need to import $default

dnolen 2021-05-24T12:36:23.016500Z

there's no magic way us to detect that you need to look at the library and see how it's exported

Michael Jung 2021-05-24T15:25:12.018800Z

@dnolen You mean like this?

(ns my-app.core (:require ["@react-navigation/native$default" :refer [NavigationContainer]]))
This doesn’t work either. Also, as we import it with curly braces in JS, it shouldn’t be a default export, right? I don’t know much about these things, though...

dnolen 2021-05-24T15:28:25.021600Z

@michael.w.jung you need to know about 🙂

dotemacs 2021-05-24T15:28:41.022200Z

I’m using this library, with shadow-cljs, and it works. I’m not saying that it’s a krell/shadow-cljs thing. It’s probably something to do with your setup… If you want to see what is available when you require a given library, require it in the REPL:

(require "@your-lib")
If you don’t, then something went wrong upstream.

dnolen 2021-05-24T15:28:53.022400Z

examine the the library, see if exports default and something else

dnolen 2021-05-24T15:30:09.023Z

@michael.w.jung also (js/require "@react-navigation/native") if that doesn't work as you said above then something else is probably wrong

dnolen 2021-05-24T15:31:58.023900Z

oh sorry - but you can't do that anyway

dnolen 2021-05-24T15:32:11.024300Z

React Native is not Node.js you have to understand this

dnolen 2021-05-24T15:32:26.024600Z

if Metro can't see it - you cannot require it

dnolen 2021-05-24T15:32:38.024900Z

Metro is never going to see your ClojureScript files - so that will never work

dnolen 2021-05-24T15:33:39.025900Z

To avoid issues like you have to understand what Krell must do to satisfy Metro

dnolen 2021-05-24T15:34:21.027600Z

1. Compiling your project will detect Node modules - this gets dumped into a file that Metro does see in the output directory

dnolen 2021-05-24T15:34:42.028100Z

2. If your Node import isn't in that file - it's never going to work

dnolen 2021-05-24T15:35:29.028600Z

look at output-dir/npm_deps.js

Michael Jung 2021-05-24T15:36:52.029500Z

It seems to be there:

module.exports = {                                                                                                                                                                                                                                                              
  npmDeps: {                                                                                                                                                                                                                                                                    
    "react-native": require('react-native'),                                                                                                                                                                                                                                    
    "react-dom": require('react-dom'),                                                                                                                                                                                                                                          
    "@react-navigation/native": require('@react-navigation/native'),                                                                                                                                                                                                            
    "react": require('react')  }                                                                                                                                                                                                                                                
}; 

dnolen 2021-05-24T15:37:08.029800Z

so

dnolen 2021-05-24T15:37:13.030200Z

if it's there then

dnolen 2021-05-24T15:37:18.030600Z

A) it was in node_modules ... good

dnolen 2021-05-24T15:37:25.031Z

B) Krell saw it ... good

dnolen 2021-05-24T15:37:37.031300Z

so you're running out of possibilities of what could be wrong

thheller 2021-05-24T15:38:35.032100Z

did you reload your RN app? new npm dependencies cannot be hot-reloaded or REPL require'd in without being there by the initial load first

dnolen 2021-05-24T15:39:29.032900Z

right there's absolutely nothing dynamic about Metro

dnolen 2021-05-24T15:39:49.033700Z

you have recompile ClojureScript & reload the entire app if you import something from node_modules

dnolen 2021-05-24T15:39:59.034Z

(for the first time)

Michael Jung 2021-05-24T15:40:19.034400Z

node_modules/@react-navigation/native/lib/module/index.js looks like this:

export * from '@react-navigation/core';                                                                                                                                                                                                                                         
export { default as NavigationContainer } from './NavigationContainer';                                                                                                                                                                                                         
...
So no default export if I understand this correctly

Michael Jung 2021-05-24T15:40:47.034900Z

Yes, I think I reloaded / rebuilt everything.

Michael Jung 2021-05-24T15:41:20.035400Z

I threw away the whole target directory and reran clj -M -m krell.main -co build.edn -c

dnolen 2021-05-24T15:43:51.036100Z

another way to debug is the edit index.js and console.log this library that you're trying to use

dnolen 2021-05-24T15:44:08.036500Z

there's nothing especially magical about the way Krell works

dnolen 2021-05-24T15:45:25.037400Z

whenever you're done debugging you can always restore index.js by running a compile

Michael Jung 2021-05-24T15:53:42.039200Z

Ok, I added the following to index.js

import { NavigationContainer } from '@react-navigation/native';                                                                                                                                                                                                                 
console.log(NavigationContainer);
console.log(typeof(NavigationContainer));
console.log(NavigationContainer === undefined);
The metro output says:
{"$$typeof": Symbol(react.forward_ref), "render": [Function NavigationContainer]}
object
false
So to me this looks like it works in JS

dnolen 2021-05-24T15:56:13.040Z

ok - so now fix up your :require to the way you originally had it

dnolen 2021-05-24T15:56:39.040400Z

now if you look at the generated JS for that namespace you should see something that looks sensible

dnolen 2021-05-24T15:57:03.040900Z

the one magic Krell trick here is this

dnolen 2021-05-24T15:57:59.042Z

there is no such thing as dynamic require in Metro - so we just monkey patch a global JS require function that will return the library then you invoke it

dnolen 2021-05-24T15:58:34.042700Z

this is how you can get a handle on modules and assets even though Metro never saw ClojureScript

dnolen 2021-05-24T15:59:05.043100Z

@michael.w.jung before you go look at though

dnolen 2021-05-24T15:59:37.043800Z

console logging the npm_deps.js import in index.js is probably more useful - it's a JS object that will be used by ClojureScript to "import" those libraries

dnolen 2021-05-24T16:00:38.044300Z

if somehow the library is null in there - then of course it can't work

Michael Jung 2021-05-24T16:07:13.044900Z

Very odd. Now the library is no longer in npm_deps.js...

dnolen 2021-05-24T16:07:54.045200Z

so this would be source of the bug if there is one

dnolen 2021-05-24T16:08:04.045500Z

if it disappears from there - of course it won't work

dnolen 2021-05-24T16:08:30.046100Z

but npm_deps.js will only get rewritten if you somehow run another compile

Michael Jung 2021-05-24T16:08:44.046500Z

I deleted the target folder and reran clj -M -m krell.main -co build.edn -c. Still gone.

dnolen 2021-05-24T16:09:11.046700Z

here's the one other thing

dnolen 2021-05-24T16:09:40.047300Z

your ClojureScript require cannot be in some random file outside of the entry point dep graph

dnolen 2021-05-24T16:10:02.047800Z

i.e. a.core is the app entrypoint and you have some side file b.core which imports Node library

dnolen 2021-05-24T16:10:10.048Z

which is never required by a.core

Michael Jung 2021-05-24T16:11:28.048900Z

Ok, that’s why it was gone. I commented out some stuff before and it no longer was in that dependency graph. It is back now that I fixed this.

dnolen 2021-05-24T16:11:44.049200Z

you are now a Krell expert 🙂

dnolen 2021-05-24T16:11:52.049500Z

there's no other rules than the above

Michael Jung 2021-05-24T16:17:50.049900Z

Well, I certainly don’t feel like one 😄

Michael Jung 2021-05-24T16:17:56.050100Z

It seems to work now

Michael Jung 2021-05-24T16:18:46.051100Z

I have no idea what I changed. It probably really was because I removed the require of the file that imported the lib when I tried to debug the issue.

dnolen 2021-05-24T16:21:17.051300Z

Michael Jung 2021-05-24T16:22:19.052200Z

Thank you very much for your help @dnolen. I was about to give up on this. Much appreciated!

dnolen 2021-05-24T16:24:10.052400Z

No problem

dnolen 2021-05-24T16:24:50.053600Z

But hopefully the above shows Krell works in a way intentionally to make debugging issues relatively straightforward

dnolen 2021-05-24T16:25:21.054100Z

And I haven’t seen a library that can’t be used

Michael Jung 2021-05-24T16:33:22.056100Z

Yes, it definitly did. I specifically chose Krell because it seemed rather simple and straightforward. I did some experiments with re-natal and expo in the past, but that was a complete mystery to me. I’m still pretty much a newbie in both CLJS and JS.

Michael Jung 2021-05-24T19:02:52.061400Z

I have added another library to my project. This time with a default export. And again, I was having quite some trouble until I finally managed to get it to run. I think I’m still missing a piece of the picture: When I add a new dependency, which steps do I need to take? I thought I have to do this: 1. npm add my-lib 2. Require the library in cljs 3. Recompile using clj -M -m krell.main -co build.edn -c 4. Restart the Android app But I think this wasn’t enough. I also did the following things in some order I don’t remember: • Delete and rebuild the target dir • Restart metro with npx react-native start • Reinstall the Android app with npx react-native run-android (I’m not building for iOS at the moment)

dnolen 2021-05-24T19:33:50.062Z

Metro also has caching problems - but otherwise I don't think any of those other steps should be necessary

dnolen 2021-05-24T19:34:30.062700Z

definitely have gotten into funny situations w/ Metro which have nothing to do w/ Krell that requires a whole cycle

dnolen 2021-05-24T19:34:55.063200Z

whatever is on disk is the truth - and if it's still not working, I think the likelihood the problem is in Krell is quite low

dnolen 2021-05-24T19:36:19.064500Z

but happy to take a specific set of steps to reproduce if you can come up w/ them - I dev on Android less so maybe it's spottier there