Welcome to Chapter 4!
In the previous Lazy Code Splitting chapter, we learned how to efficiently load our code only when needed.
Now that the system has loaded our help.tsx file, we face a design challenge: How do we organize the code inside it?
Do we write one giant function that calculates data, handles key presses, and draws pixels to the screen all at once? No. That would be a mess. Instead, we use a technique called Declarative UI Composition.
Imagine you want to build a house. You hire one person. They pour the concrete, wire the electricity, paint the walls, and install the windows.
If the painting looks bad, you have to distract the person while they are pouring concrete to fix it. If the electricity fails, the painting stops. This is Coupled Logic. It is hard to manage because one person is doing too many different types of jobs.
A better way to build a house is:
In our project:
call function in help.tsx. It manages the data.HelpV2 component. It handles the visuals.Our goal is to display a list of available commands (like "Settings", "Profile", "Search") to the user.
call function receives this list from the system.call function passes this list to HelpV2.HelpV2 draws it on the screen.Let's look at how we compose this relationship.
First, let's look at our help.tsx file again. Its job is to prepare the data.
// help.tsx
export const call: LocalJSXCommandCall = async (
onDone,
{ options: { commands } } // We extract the data here
) => {
// Logic layer: We have the data ('commands')
// We are ready to hire the painter.
// ... return the UI
};
Explanation:
The call function acts as the Logic Layer. It extracts commands (the list of tools) and onDone (the signal to finish). It does not know how to draw a list. It just holds the data.
We import a specialized component called HelpV2. This component is defined elsewhere (in a purely visual file).
// help.tsx
import { HelpV2 } from '../../components/HelpV2/HelpV2.js';
// ... inside the call function ...
return <HelpV2 commands={commands} onClose={onDone} />;
Explanation: This single line is the essence of Declarative Composition.
<HelpV2 /> component here."We pass the "work order" via props:
commands={commands}: Here is the data to paint.onClose={onDone}: Here is the button to press when the user quits.Imperative (The Old Way):
"Go to the kitchen. Open the drawer. Get a spoon. Scoop ice cream. Put it in a bowl."
Declarative (The React Way):
"I want a bowl of ice cream."
By returning <HelpV2 />, we are focusing on the result, not the step-by-step drawing instructions.
How does the data flow from the system, through our logic, to the visual component?
help.tsx).context).<HelpV2 />) with that data attached.
Let's look closer at the connection point in help.tsx. This is where the Logic layer shakes hands with the UI layer.
// help.tsx
export const call: LocalJSXCommandCall = async (onDone, context) => {
// 1. Get the data
const commandList = context.options.commands;
// 2. Delegate to the UI Component
return (
<HelpV2
commands={commandList}
onClose={onDone}
/>
);
};
Explanation:
HelpV2. We don't touch this file.HelpV2.This makes our code much safer and easier to update.
In this chapter, we learned about Declarative UI Composition:
call function acts as the Controller, gathering data.HelpV2 component acts as the View, displaying the data.<HelpV2 />) to declaratively describe what we want to show.Now the UI is on the screen! But a user interface isn't a static painting; it needs to live, react to inputs, and eventually disappear. How do we know when the user has opened or closed the command?
To handle this, we need to understand the lifecycle of our command.
Next Chapter: Lifecycle Management
Generated by Code IQ