Skip to main content
RapidDev - Software Development Agency
flutterflow-tutorials

How to Add Components to Your FlutterFlow Screens

FlutterFlow Components are reusable UI pieces you build once and place on multiple screens. Create a Component in the left sidebar → Components panel, define Component Parameters for dynamic data, add Callback Actions for parent-to-child communication, and use Component State for internal state. Drag the component from the Components panel onto any page and fill in its parameters.

What you'll learn

  • How to create a reusable Component in FlutterFlow
  • How to define Component Parameters to pass data into a component
  • How to use Callback Actions so components can communicate with their parent page
  • How to manage internal state with Component State variables
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner11 min read20-30 minFlutterFlow Free+March 2026RapidDev Engineering Team
TL;DR

FlutterFlow Components are reusable UI pieces you build once and place on multiple screens. Create a Component in the left sidebar → Components panel, define Component Parameters for dynamic data, add Callback Actions for parent-to-child communication, and use Component State for internal state. Drag the component from the Components panel onto any page and fill in its parameters.

Building Reusable UI with FlutterFlow Components

A Component in FlutterFlow is equivalent to a custom widget in Flutter — a reusable piece of UI that you design once and place on as many pages as you need. Without components, you find yourself rebuilding the same header, card layout, or navigation bar on every page. When you need to update the design, you have to change it in 20 places. Components solve this: design it once, update it once, and every page reflects the change. FlutterFlow's Components system supports Parameters (data flowing in from the parent), Callback Actions (events flowing out to the parent), Component State (internal state for things like toggle state or input values), and nesting (components inside components). This guide walks through creating a ProductCard component as a practical example.

Prerequisites

  • A FlutterFlow project with at least two or more pages
  • Basic understanding of FlutterFlow's widget tree and properties panel
  • A Firestore collection to bind component data to (optional but helpful for the example)

Step-by-step guide

1

Create a new Component

In the left sidebar, look for the 'Components' icon (it looks like a building block or puzzle piece) or navigate to the sidebar's 'UI Builder' section and find the 'Components' tab. Click the '+' button to create a new Component. Give it a descriptive name in PascalCase — for example, 'ProductCard'. FlutterFlow opens a new canvas for the Component, which is a blank container to start. This canvas works exactly like a page canvas — you can add any widgets, set up layouts, and apply theme styles. The Component canvas has a width and height you can set to match its intended use (e.g., a card width of 200 for a grid item).

Expected result: A new Component named 'ProductCard' is created and you are on its blank canvas in the FlutterFlow editor.

2

Build the component UI

Design the ProductCard component UI on the component canvas. Add a Container with rounded corners and a shadow. Inside, add a Column. Add an Image widget at the top (for the product image), then a Text widget for the product name, another Text for the price, and a Button at the bottom for 'Add to Cart'. Apply styling from your theme — use theme colors and typography rather than hardcoded values so the component respects your app's design system. Do not bind any real data yet — use placeholder strings and colors. The data will flow in through Parameters in the next step.

Expected result: The ProductCard component has a complete visual layout with Image, product name Text, price Text, and an Add to Cart Button, all using theme values.

3

Define Component Parameters

With the ProductCard component open, find the 'Parameters' section in the component's settings panel (click outside all widgets to see the component-level properties). Tap 'Add Parameter' and add: 'productName' (String, required), 'price' (double, required), 'imageUrl' (String, required), 'productId' (String, required). Parameters are the data that the parent page passes into the component — each instance of the card can show different product data. After defining parameters, go back to the component canvas and update each widget binding: bind the Image widget's URL to the 'imageUrl' parameter, the product name Text to 'productName', the price Text to a Custom Function that formats the double as currency using the 'price' parameter.

Expected result: The ProductCard component has four defined parameters and each widget in the component is bound to the appropriate parameter via 'Set from Variable → Component Parameters'.

4

Add a Callback Action for the Add to Cart button

Callback Actions let the component send events back to the parent page. In the ProductCard component, select the 'Add to Cart' button. Open its Action Flow. Add a 'Callback Action' step — this is different from a regular action. Name it 'onAddToCart'. The parent page that uses this component will provide the actual implementation of what happens when this callback fires (e.g., update a cart Firestore collection). The component itself does not know or care what the parent does — it just fires the callback. Define the callback with a single argument: 'productId' (String). Now in the button's action flow, call the 'onAddToCart' Callback Action and pass the component's productId parameter as the argument.

Expected result: The ProductCard component has an 'onAddToCart' Callback Action defined. The Add to Cart button's Action Flow calls this callback with the productId.

5

Add a Component to a page

Navigate to a page where you want to display ProductCards — for example, a Products listing page. In the left sidebar, open the Components panel and drag your 'ProductCard' component onto the page canvas. FlutterFlow shows a parameter fill-in dialog: enter the values for productName, price, imageUrl, and productId. For a static test, enter literal string values. For dynamic data, close the dialog and bind each parameter to a Firestore query result. Add a Backend Query on the page that fetches from the 'products' collection, then place the ProductCard inside a Repeating Group and bind each parameter to the corresponding Firestore document field. Set the Callback Actions: for 'onAddToCart', add the action you want to run on the parent page (e.g., create a cart item in Firestore).

Expected result: ProductCard components appear on the page, each showing different product data from the Firestore query. Tapping Add to Cart fires the callback and runs the parent page's cart action.

6

Add Component State for internal toggle behavior

Component State is for data that lives entirely within the component — for example, whether a product is bookmarked (before saving to Firestore). In the ProductCard component settings, find 'Component State' and add a Boolean variable named 'isBookmarked' with a default value of false. Add a bookmark icon button to the component. Bind the icon's color to a conditional: if isBookmarked is true, show a filled bookmark icon in your accent color; if false, show an outlined bookmark icon. Add an action to the bookmark button that toggles the isBookmarked Component State value. This state is local to the component instance — each card on the page has its own isBookmarked state.

Expected result: The bookmark button on each ProductCard independently toggles between filled and outlined states without affecting other cards on the page.

Complete working example

product_card_structure.dart
1// FlutterFlow Components are built visually — this file shows the equivalent
2// Flutter widget structure for documentation and Custom Widget reference.
3// You do NOT write this code in FlutterFlow — build it visually instead.
4
5// Component: ProductCard
6// Parameters: productName (String), price (double), imageUrl (String), productId (String)
7// Callbacks: onAddToCart(productId: String)
8// Component State: isBookmarked (Boolean, default: false)
9
10import 'package:flutter/material.dart';
11
12class ProductCard extends StatefulWidget {
13 const ProductCard({
14 super.key,
15 required this.productName,
16 required this.price,
17 required this.imageUrl,
18 required this.productId,
19 required this.onAddToCart,
20 });
21
22 final String productName;
23 final double price;
24 final String imageUrl;
25 final String productId;
26 final void Function(String productId) onAddToCart;
27
28 @override
29 State<ProductCard> createState() => _ProductCardState();
30}
31
32class _ProductCardState extends State<ProductCard> {
33 // Component State: internal to this card instance
34 bool _isBookmarked = false;
35
36 @override
37 Widget build(BuildContext context) {
38 return Card(
39 elevation: 2,
40 shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
41 child: Column(
42 crossAxisAlignment: CrossAxisAlignment.start,
43 children: [
44 ClipRRect(
45 borderRadius:
46 const BorderRadius.vertical(top: Radius.circular(12)),
47 child: Image.network(
48 widget.imageUrl,
49 height: 160,
50 width: double.infinity,
51 fit: BoxFit.cover,
52 ),
53 ),
54 Padding(
55 padding: const EdgeInsets.all(12),
56 child: Column(
57 crossAxisAlignment: CrossAxisAlignment.start,
58 children: [
59 Row(
60 mainAxisAlignment: MainAxisAlignment.spaceBetween,
61 children: [
62 Expanded(
63 child: Text(
64 widget.productName,
65 style: Theme.of(context).textTheme.titleMedium,
66 overflow: TextOverflow.ellipsis,
67 ),
68 ),
69 // Bookmark toggle (Component State)
70 IconButton(
71 icon: Icon(
72 _isBookmarked ? Icons.bookmark : Icons.bookmark_border,
73 color: _isBookmarked ? Colors.amber : Colors.grey,
74 ),
75 onPressed: () =>
76 setState(() => _isBookmarked = !_isBookmarked),
77 ),
78 ],
79 ),
80 Text('\$${widget.price.toStringAsFixed(2)}'),
81 const SizedBox(height: 8),
82 // Callback action button
83 ElevatedButton(
84 onPressed: () => widget.onAddToCart(widget.productId),
85 child: const Text('Add to Cart'),
86 ),
87 ],
88 ),
89 ),
90 ],
91 ),
92 );
93 }
94}

Common mistakes when adding Components to Your FlutterFlow Screens

Why it's a problem: Hardcoding data inside a component instead of using Component Parameters

How to avoid: Define a Component Parameter for every piece of data that should change between instances. Bind each widget in the component to 'Set from Variable → Component Parameters → [parameterName]'. The parent page supplies the actual values.

Why it's a problem: Using App State to store component-specific internal state

How to avoid: Use Component State (defined in the component's settings panel) for state that belongs to a single instance of the component. App State is for data that genuinely needs to be shared across the whole app (like the current user's role or cart item count).

Why it's a problem: Not assigning actions to Callback Actions on the parent page

How to avoid: After placing a component on a page, select it in the widget tree and check the 'Callbacks' section in the properties panel. Assign an action flow to every defined callback. FlutterFlow should warn you about unassigned required callbacks.

Why it's a problem: Building the same UI on multiple pages instead of extracting it into a component

How to avoid: Any UI that appears on two or more pages should be extracted into a Component. Use FlutterFlow's 'Convert to Component' feature (right-click a widget in the widget tree) to extract existing widgets into a reusable component.

Best practices

  • Name components for what they represent ('ProductCard', 'UserAvatar', 'NavBar'), not how they look ('BlueCard', 'RoundImage') — appearances change, purpose does not.
  • Use Component Parameters for ALL data that varies between instances — never hardcode strings, colors, or URLs that might differ per use.
  • Keep components focused: a ProductCard should handle displaying a product. It should not also handle cart management, navigation, and analytics logging — those belong in the parent page's Callback Actions.
  • Use Component State for temporary visual state (expanded/collapsed, bookmarked/unbookmarked) and App State or Firestore for persistent state.
  • Test each component in isolation before placing it on a page — FlutterFlow's component canvas lets you preview it with test parameter values.
  • Build a 'Component Library' page in your project that displays all your components side by side with their names — this serves as living documentation for your design system.
  • Apply theme colors and typography inside components rather than hardcoded hex values — this ensures components automatically update when you change your app's theme.
  • Nest components thoughtfully — a ListItem component can contain an Avatar component, but deep nesting (4+ levels) makes the widget tree hard to navigate and debug.

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I'm building a FlutterFlow app and want to create a reusable ProductCard component. It should display: a product image (from a URL), product name, price formatted as currency, and an Add to Cart button. It needs to receive product data through Component Parameters and trigger a Callback Action when the cart button is tapped. It should also have a Component State boolean for a bookmark toggle. Please describe the structure of this component in terms of FlutterFlow's visual builder — widgets, parameters, and callback setup — not as code.

FlutterFlow Prompt

I need to convert my FlutterFlow ProductCard UI into a reusable Component. The card currently has: Image widget (URL hardcoded), Text widget (name hardcoded), Text widget (price hardcoded), and an ElevatedButton. What Component Parameters should I define, how should I bind each widget to those parameters, what Callback Action should the button fire, and how do I set up the parent page to pass data and handle the callback? Describe the FlutterFlow editor steps only.

Frequently asked questions

What is the difference between a FlutterFlow Component and a regular widget?

A regular widget is a built-in FlutterFlow UI element (Text, Button, Image, etc.) that you configure individually on each page. A Component is a reusable group of widgets you design yourself — it can contain multiple built-in widgets, have its own parameters and state, and be placed on any page. Components are equivalent to custom Flutter widgets in a coded app.

Can I nest one Component inside another Component?

Yes. You can place a Component inside another Component on the component canvas. This is useful for building composite design systems — a ProductCard component can contain a UserAvatar component. Just be careful not to create deeply nested structures (more than 4 levels) as they become difficult to navigate and debug.

How do I update all instances of a Component when I change its design?

This is the core benefit of Components. When you edit the Component's canvas design, every page that uses that Component automatically reflects the change — you do not need to update each page individually. This is why extracting repeated UI into Components is so valuable for app maintenance.

What is the difference between Component Parameters and Component State?

Component Parameters are data passed IN from the parent page when the component is placed — they are set by the parent and the component reads them. Component State is internal data managed within the component itself — the component creates it, reads it, and updates it without the parent being involved. Parameters flow in; state lives inside.

Can I use a Component in a Repeating Group to show a list of items?

Yes, and this is one of the most common patterns. Place your Component inside a Repeating Group (ListView) and bind the Component's Parameters to the Repeating Group's data source fields. Each item in the list gets its own Component instance with its own parameter values and its own Component State.

How do I access data from the parent page inside a Component?

Define a Component Parameter for each piece of parent data the component needs. The parent page passes the value when it places the component. Components cannot directly access the parent page's variables — all data must flow through explicitly defined Parameters. This is intentional: it keeps components portable and decoupled from specific pages.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.