Welcome to the final chapter of this series!
In the previous chapter, UI Component Delegation, we built a nice looking "Green Box" in our terminal. However, right now, it is just a pretty picture. It doesn't know anything about our application, and worse, if you run it, you might notice you can't actually exit it without pressing Ctrl+C.
Today, we are going to breathe life into our component using Context & Lifecycle Injection.
Imagine you hire a contractor to renovate your kitchen.
contextβdata the command needs to know to do its job (like "Who is the user?" or "Where are we running?").onDoneβa specific signal the command sends to say "I am finished, take control back."Without Context, the command is blind. Without Lifecycle (the radio), the command is stuck running forever.
We want to upgrade our "Task Manager" box from Chapter 4 to do two things:
Enter key.
We are going back to our BackgroundTasksDialog.tsx file. We previously accepted onDone and toolUseContext as props, but we didn't use them. Let's wire them up.
To use the "Radio" (onDone), we need a trigger. In a graphical interface, this would be a "Close" button. In a terminal, it's usually a keyboard press.
We use a hook called useInput from the ink library.
// src/components/tasks/BackgroundTasksDialog.tsx
import { useInput } from 'ink';
// Inside the component...
useInput((input, key) => {
// If the user presses 'Enter' (return)
if (key.return) {
// Call the "Radio" to signal we are finished!
onDone();
}
});
Explanation:
useInput: This sets up a listener for keyboard events.key.return: Checks if the specific key pressed was "Enter."onDone(): This executes the function passed down from the main app. It tells the system "Exit now."
Now let's look at the Blueprint (toolUseContext). This object holds helpful global data. For this tutorial, we will display the cwd (Current Working Directory).
// Inside the component...
// We extract the 'cwd' (current folder path) from the context
const currentFolder = toolUseContext.cwd;
Explanation:
toolUseContext: We received this as a prop in the previous chapter..cwd: This is a piece of data automatically provided by the framework. It tells us where the user triggered the command.Let's update our render function to show this information.
return (
<Box borderStyle="round" borderColor="green" flexDirection="column">
<Text bold>Task Manager</Text>
{/* Displaying context data */}
<Text>Folder: {currentFolder}</Text>
<Text color="gray">Press Enter to exit</Text>
</Box>
);
Explanation:
flexDirection="column" to stack the text lines vertically.{currentFolder} variable we pulled from the context.onDone logic we wrote.
How does this "Injection" actually work? How does the cwd get into the context, and how does onDone actually kill the program?
Think of it like a Relay Race.
The baton (Context & Lifecycle) is passed from the very top of the application down to your specific component.
Let's look at the code inside the Main Application (the framework) that starts this chain reaction.
1. Creating the Lifecycle (onDone)
At the very root of the application, there is a function that wraps Node.js's native exit command.
// internal-framework/lifecycle.ts
// This is the implementation of 'onDone'
const handleCompletion = (result?: any) => {
// Clean up any temporary files...
cleanup();
// Kill the process successfully (code 0)
process.exit(0);
};
2. Creating the Context
Before loading your command, the app gathers information about the environment.
// internal-framework/context.ts
const globalContext = {
// Node.js command to get current folder
cwd: process.cwd(),
// Reading a config file from the disk
config: readConfigFile('my-app.json'),
// Checking environment variables
isDebug: process.env.DEBUG === 'true',
};
3. The Injection
Finally, the framework calls the call function we wrote in React-based Command Handler and "injects" these two objects.
// internal-framework/runner.ts
// This calls the code you wrote in Chapter 3!
await tasksCommand.call(handleCompletion, globalContext);
By the time the data reaches your Green Box component, it has traveled through three layers of abstraction!
context and a fake onDone function. You don't need to run the whole real application to check if the box looks right.context, ensuring all tools behave the same way.
Congratulations! You have completed the basic tutorial for the tasks project.
Let's review what we built across these five chapters:
tasks) and a "business card."You now have a fully functional, interactive CLI tool that follows best practices for performance and architecture. You are ready to start building your own features!
Generated by Code IQ