Utilities and UI components for cross-platform React Native apps
0

Configure Feed

Select the types of activity you want to include in your feed.

docs: add submodule installation instructions

Submodules usage is more tedious to configure, but provides the key
benefit of allowing hot-reloading of library code edits while running
the host project.

Great when working on the library from the context of a host application!

Joseph Hale (Dec 26, 2025, 1:39 PM -0700) c053628f e5ca8e6c

+131
+63
README.md
··· 24 24 npm install react-native-expressive 25 25 ``` 26 26 27 + <details> 28 + <summary><strong>Submodule Usage</strong></summary> 29 + 30 + This library can also be used as a [Git 31 + Submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules), which can 32 + enable hot reloading of library codes changes. 33 + 34 + The tradeoff is the host app is then responsible for including the library's 35 + dependencies directly within the host's `package.json` and configuring any 36 + needed aliases to resolve library items from the submodule path. 37 + 38 + **Install the submodule** 39 + 40 + ```bash 41 + git submodule add https://github.com/thehale/react-native-expressive.git lib/react-native-expressive 42 + ``` 43 + 44 + **Install the submodule's dependencies** 45 + 46 + ```bash 47 + node ./lib/react-native-expressive/script/install-dependencies-in-host.js 48 + ``` 49 + 50 + **Configure Aliases** 51 + 52 + _babel.config.js_ 53 + ```diff 54 + module.exports = { 55 + plugins: [ 56 + + [ 57 + + 'module-resolver', 58 + + { 59 + + extensions: ['.ios.js', '.android.js', '.ios.jsx', '.android.jsx', '.js', '.jsx', '.json', '.ts', '.tsx'], 60 + + root: ['.'], 61 + + alias: { 62 + + 'react-native-expressive': './lib/react-native-expressive/src', 63 + + }, 64 + + }, 65 + + ] 66 + ] 67 + } 68 + ``` 69 + 70 + _tsconfig.json_ 71 + ```diff 72 + { 73 + "compilerOptions": { 74 + "paths": { 75 + + "react-native-expressive": ["./lib/react-native-expressive/src"] 76 + } 77 + } 78 + } 79 + ``` 80 + 81 + > [!TIP] 82 + > You may have to `npx react-native clean` the Metro and npm caches followed by an 83 + > app reinstall. 84 + 85 + > [!TIP] 86 + > Make sure your `react-native-expressive` submodule does **NOT** have a 87 + > `node_modules` folder as that can break Metro's module resolution. 88 + 89 + </details> 27 90 28 91 ## Usage 29 92
+68
script/install-dependencies-in-host.js
··· 1 + // Copyright (c) 2025 Joseph Hale 2 + // 3 + // This Source Code Form is subject to the terms of the Mozilla Public 4 + // License, v. 2.0. If a copy of the MPL was not distributed with this 5 + // file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 + 7 + const fs = require('node:fs'); 8 + const path = require('node:path'); 9 + const readline = require('node:readline'); 10 + const { exec } = require('child_process'); 11 + 12 + function main() { 13 + const thisScriptPath = process.argv[1]; 14 + const thisPackageJsonPath = path.join( 15 + path.dirname(thisScriptPath), 16 + '..', 17 + 'package.json' 18 + ); 19 + const thisPackageJson = JSON.parse( 20 + fs.readFileSync(thisPackageJsonPath, 'utf-8') 21 + ); 22 + 23 + const dependencies = Object.entries(thisPackageJson.dependencies).map( 24 + ([packageName, version]) => `${packageName}@${version}` 25 + ); 26 + const command = `npm install --save ${dependencies.join(' ')}`; 27 + 28 + const devDependencies = ["babel-plugin-module-resolver@^5.0.2"] 29 + const devCommand = `npm install --save-dev ${devDependencies.join(' ')}`; 30 + 31 + console.log("How to install dependencies:"); 32 + console.log(); 33 + console.log(` ${command}`); 34 + console.log(` ${devCommand}`); 35 + console.log(); 36 + 37 + const rl = readline.createInterface({ 38 + input: process.stdin, 39 + output: process.stdout, 40 + }); 41 + rl.question(`Run now? (Y/n)`, (answer) => { 42 + if (['y', ''].includes(answer.toLowerCase())) { 43 + console.log('-'.repeat(40)); 44 + (async () => { 45 + await shell(command) 46 + await shell(devCommand) 47 + })(); 48 + } 49 + rl.close(); 50 + }); 51 + } 52 + 53 + function shell(command) { 54 + return new Promise((resolve) => { 55 + exec(command, (error, stdout, stderr) => { 56 + console.log(stdout); 57 + if (error) { 58 + console.error(`Error executing command: ${error.message}`); 59 + } 60 + if (stderr) { 61 + console.error(`stderr: ${stderr}`); 62 + } 63 + resolve(); 64 + }); 65 + }); 66 + } 67 + 68 + main();