- Published on
Make CLI app with React
- Authors
- Name
- Nico Prananta
- Follow me: @2co_p
React has been around for a while and has been adopted for many kinds of apps, not only web apps but also mobile native apps. But did you know that you can use React to make a command-line app? Using ink, we can use React to create interactive and sleek-looking command-line apps!
To give an example, I made a small demo CLI app. It's a real-time chat app using Supabase's Realtime feature. Here is the main React component called App
:
export default function App({
room,
nickname,
supabaseKey,
supabaseUrl,
}: Props) {
const supabase = createClient(supabaseUrl, supabaseKey);
const channel = supabase.channel(room);
const [userInput, setUserInput] = useState('');
const [messageToSend, setMessageToSend] = useState('');
const [isSending, setIsSending] = useState(false);
useInput((input, key) => {
if (key.return) {
setMessageToSend(userInput);
setUserInput('');
} else if (key.backspace || key.delete) {
setUserInput((curr) => curr.slice(0, -1));
} else {
setUserInput((curr) => curr + input);
}
});
useEffect(() => {
if (!isSending && messageToSend.trim().length > 0) {
if (messageToSend.trim() === '\\quit') {
process.exit();
}
setIsSending(true);
channel
.send({
type: 'broadcast',
event: 'test-my-messages',
payload: {
user: nickname,
content: messageToSend,
id: nanoid(),
},
})
.then(() => {
setMessageToSend('');
setIsSending(false);
});
}
}, [messageToSend, isSending, channel]);
const [messages, setMessages] = useState<Array<Message>>([
{
user: 'Room',
content: room,
id: `the-room`,
},
]);
useEffect(() => {
const subscription = channel
.on('broadcast', { event: 'test-my-messages' }, ({ payload }) => {
setMessages((curr) => {
const newMessages = Array.from(
new Set([...curr, payload as Message])
);
return newMessages;
});
})
.subscribe();
return () => {
subscription.unsubscribe().then(() => {});
};
}, []);
return (
<Box>
<Static items={messages}>
{(m) => {
if (m.id === 'the-room') {
return (
<Box key={m.id}>
<Text color="magenta" bold>
Room:
</Text>
<Text>: {m.content}</Text>
</Box>
);
}
return (
<Box key={m.id}>
<Text color="green">{m.user === nickname ? 'You' : m.user}</Text>
<Text>: {m.content}</Text>
</Box>
);
}}
</Static>
<Text>{userInput}</Text>
</Box>
);
}
I found it really cool that I can use useEffect
and useState
to handle events and state in the CLI app. ❤️
Here's the demo video:
You can find the repository here. Have fun!
Are you working in a team environment and your pull request process slows your team down? Then you have to grab a copy of my book, Pull Request Best Practices!