Create an interactive React Native template
This is a guide on how to create a simple template for your future React Native apps while letting the user add and/or drop some of its features.
You can easily use a template to create your app with the React Native cli, for example using react-native-community's Typescript template:
npx react-native init MyApp --template react-native-template-typescript
To create a custom static template, create an app with all the features you need (eg: setup Typescript, some essential libraries or other details).
Then move everything inside a folder named template
, this will define the basis of your template.
Next to the template
folder create a script named: template.config.js
:
module.exports = {
placeholderName: 'ReactNativeTemplate',
templateDir: './template'
};
placeholderName
can be anything, it will temporarily be the name of the project and will be replaced by the name of the app when you init a new project with the React Native clitemplateDir
is the path to the folder we created that contains the custom template
_ template/
| |_ src
| |_ ios
| |_ android
| |_ ...
|
|_ template.config.js
That's it for a static template !
To test this:
- locally
npx react-native init <app-name> --template file://<absolute-path-to-template>
- if you push to Github
npx react-native init <app-name> --template https://github.com/<template-url>
- if you publish to NPM
npx react-native init <app-name> --template <npm-lib-name>
Now, to make this template a bit more dynamic...
We will need install the inquirer package and with it, query the user on various topics.
npm install inquirer
To do so, modify your template.config.js
:
module.exports = {
placeholderName: 'ReactNativeTemplate',
templateDir: './template',
postInitScript: './scripts/postInitScript.ts',
};
The postInitScript
file is executed after the template's initialisation and before the dependencies are installed.
Add a new scripts/postInitScript.ts
file, this will contain everything we need to query the user.
In this file we need to indicate that we will use a Typescript to execute the script:
#!/usr/bin/env ts-node
If you prefer using Javascript, replacets-node
withnode
First, start by setting up the spinner to match the React Native cli look:
#!/usr/bin/env ts-node
import ora from 'ora';
const spinner = ora('This is the post-init script');
new Promise((resolve) => {
spinner.start();
// do something
}).then(() => {
spinner.succeed();
}).catch((error) => {
spinner.fail(error);
throw new Error('Something went wrong during the post init script execution');
});
Here we create a spinner using ora and control its state during the execution of our script.
Let's imagine we need to ask the user if they need to have a specific library setup, eg: React Query to handle queries like a pro
import inquirer from 'inquirer';
const QUESTIONS: inquirer.QuestionCollection<{ libraries: string[] }> = [
{
name: "reactQuery",
"type": "confirm",
default: false,
"message": "Do you need react-query ?"
}
];
const inquire = (callback: () => void) => inquirer.prompt(QUESTIONS)
.then((answers) => {
console.log("answers", answers)
// do something
callback();
});
export {
inquire
}
Import this function in your `postInitScript` file and use it after the spinner starts
With inquirer
you can easily query the user, there are different types of prompts (eg: multiple choices, yes/no, text, ...). This will simply prompt the user to answer yes or no for the question to install react-query
.
When the promise successfully resolves (when the user has answered the question correctly and not exited the script), you can act on this answer.
const inquire = (callback: () => void) => inquirer.prompt(QUESTIONS)
.then((answers) => {
console.log("answers", answers)
if(answers.reactQuery) {
console.log("react-query installed")
}
callback();
});
Then we can add the new dependency inside the template's package.json
file:
const inquire = (callback: () => void) => inquirer.prompt(QUESTIONS)
.then((answers) => {
if(answers.reactQuery) {
// read current file
const packageJsonContent = fs.readFileSync(PACKAGE_JSON_PATH, { encoding: 'utf8' });
const projectPackageJson = JSON.parse(packageJsonContent);
// add new item to current dependencies
const newPackageJson = {
...projectPackageJson,
dependencies: {
...projectPackageJson.dependencies,
'react-query': '^3.34.19'
}
};
// write changes to file
fs.writeFileSync(PACKAGE_JSON_PATH, JSON.stringify(newPackageJson, null, 2) + os.EOL);
}
callback();
});
Since the dependencies were not installed yet at this stage, we can just add the new library inside the template/package.json
file.
When the post-init script resolves, the cli will continue on to install the dependencies and finish seting-up the new app.
Read the complete code here.
You can now modify the template however you want !
Book a React training!