DEPRECATION NOTICE UI Kit 1 is now in the deprecation period. This version will no longer be supported or functional after 28 Feb 2025
To support your upgrade, please use the following guides:
We highly recommend using the latest version of UI Kit to quickly build your user interface with its updated library of components.
This page is about the previous version of UI Kit.
We highly recommend upgrading to and utilizing the latest version. Get started with UI Kit's latest library of components to quickly build your user interface.
UI kit 1 hooks are functions that let you manage the data
you need to render your app. They can be added to your app's index.jsx
file.
This hook adds and updates local state to a component.
Here is an example of useState
to create a counter app.
1 2import ForgeUI, { useState, Button, Macro, render } from '@forge/ui'; const App = () => { const [count, setCount] = useState(0); return ( <Button text={`Count is ${count}`} onClick={() => { setCount(count + 1); }} /> ); }; export const run = render(<Macro app={<App />} />);
1 2function useState<V>( initialValue: V | (() => V) | (() => Promise<V>) ): [V, (newState: V) => void];
This hook manages local state in a similar way to the useState
hook, providing a more complex
reducer argument to update state.
Here is an example of useAction
to create a counter app.
1 2import ForgeUI, { useAction, Button, Macro, render } from '@forge/ui'; const App = () => { const [count, setCount] = useAction( (currentCount, step) => currentCount + step, 0 ); return ( <Button text={`Count is ${count}`} onClick={() => { // what we call "setCount" with will be "step" in reducer setCount(1); }} /> ); }; export const run = render(<Macro app={<App />} />);
1 2function useAction<V, P>( reducer: (currentState: V, payload: P) => V | Promise<V>, initialValue: V | (() => V) | (() => Promise<V>) ): [V, (payload?: P) => void];
This hook executes a given function when one of the variables in the hook's second argument, which is the dependency array, changes its value.
Here is an example of useEffect
to create a counter app.
1 2import ForgeUI, { Text, useEffect, useState, Fragment } from '@forge/ui'; const sendLog = async () => Promise.resolve('send!'); const LogData = ({ counter }) => { const [logSend, setLogSend] = useState(); useEffect(async () => { await sendLog(); setLogSend(Date.now()); }, [counter]); return <Text>Last log: {logSend}</Text>; }; const App = () => { const [count, setCount] = useState(0); return ( <Fragment> <Button text={`Count is ${count}`} onClick={() => { setCount(count + 1); }} /> <LogData counter={count} /> </Fragment> ); }; export const run = render(<Macro app={<App />} />);
1 2function useEffect = ( onChange: () => void | Promise<void>, dependencies: (boolean | string | number | object)[] ): void;
string
, number
or boolean
, or an object
or array
of these types.This hook doesn't return anything.
This hook reads the context in which the component is currently running.
For Bitbucket, the ProductContext
would contain an extra field workspaceId
. This is the Bitbucket workspace UUID of the application on which the extension is working.
Here is an example of an app that displays all its context information with useProductContext
.
1 2import ForgeUI, { useProductContext, Text, Macro, render } from '@forge/ui'; const App = () => { const context = useProductContext(); return <Text>All info about my context: {JSON.stringify(context)}</Text>; }; export const run = render(<Macro app={<App />} />);
1 2function useProductContext(): ProductContext; interface ProductContext { accountId?: string; accountType?: AccountType; cloudId?: string; workspaceId?: string; contentId?: string; localId?: string; spaceKey?: string; environmentId?: string; environmentType?: string; installContext?: string; platformContext?: PlatformContext; extensionContext?: ExtensionContext; license?: LicenseDetails; } type AccountType = 'licensed' | 'unlicensed' | 'customer' | 'anonymous'; interface PlatformContext { type: string; } interface JiraContext extends PlatformContext { type: 'jira'; issueId: string; issueKey: string; issueType: string; projectId: string; projectKey: string; projectType: string; } interface ExtensionContext { type: string; } interface DashboardGadgetExtensionContext extends ExtensionContext { type: 'dashboardGadget'; gadgetConfiguration: { [string]: string | boolean | number }; } interface LicenseDetails { isActive: boolean; }
ProductContext: An object containing contextual information about the current environment in which the component is running; all values are optional, depending on where the component is used.
license
is undefined
for free apps, apps not listed on the Atlassian Marketplace, and apps in development and staging environments.
See the LicenseDetails
type for what information is available.JiraContext: Contextual information returned when the component is running in Jira.
'jira'
).DashboardGadgetExtensionContext: Contextual information returned by the jira:dashboardGadget
module.
'dashboardGadget'
).dashboardGadgetEdit
module. For example, { "name": "John" }
.This hook retrieves the configuration values for a macro.
Use configuration to store general data, but not sensitive information. The configuration data is stored in plaintext, so other users and apps can access and modify the values.
Here is an example of accessing configuration for a Forge macro.
1 2import ForgeUI, { useConfig, Text, TextField, Macro, MacroConfig, render, } from '@forge/ui'; const App = () => { // Retrieve the configuration const config = useConfig(); // Use the configuration values return ( <Text> {config.name} is {config.age} years old. </Text> ); }; export const run = render(<Macro app={<App />} />); // Function that defines the configuration UI const Config = () => { return ( <MacroConfig> <TextField name="name" label="Pet name" /> <TextField name="age" label="Pet age" /> </MacroConfig> ); }; export const config = render(<Config />);
1 2interface ExtensionConfiguration { [key: string]: any; } function useConfig(): ExtensionConfiguration;
None
MacroConfig
component.This hook reads, writes, or updates the content properties in the Confluence page where the app is installed.
When using this event, your Forge app must have permission from the site admin to access the data it provides within the event payload. The OAuth scope required is documented under each product event.
Running the forge lint
command picks up these required scopes.
You'll need to add the @forge/ui-confluence
to your app's dependencies. Run this command in the
directory:
1 2npm install @forge/ui-confluence
Here is an example of an app that stores information in a content property with useContentProperty
.
1 2import ForgeUI, { Button, Macro, render } from '@forge/ui'; import { useContentProperty } from '@forge/ui-confluence'; const App = () => { const [count, setCount] = useContentProperty('count', 0); return ( <Button text={`Count is ${count}`} onClick={async () => { // replace current value (regardless of if changed by someone else) await setCount(count + 1); }} /> ); }; export const run = render(<Macro app={<App />} />);
Here's another example that updates the content property based on the current value stored in the property.
1 2import ForgeUI, { Button, Macro, render } from '@forge/ui'; import { useContentProperty } from '@forge/ui-confluence'; const App = () => { const [count, setCount] = useContentProperty('count', 0); return ( <Button text={`Count is ${count}`} onClick={async () => { // update current value (avoids overwriting someone else's change) await setCount((prevCount) => prevCount + 1); }} /> ); }; export const run = render(<Macro app={<App />} />);
1 2function useContentProperty<V>( key: string, defaultValue: V ): [ V, ((value: V | ((prevValue: V) => V), retries?: number) => Promise<V>), () => Promise<void> ];
forge-${localId}-${key}
.This hook reads, writes, or updates the issue properties for the Jira issue that the component is on.
When using this event, your Forge app must have permission from the site admin to access the data it provides within the event payload. The OAuth scope required is documented under each product event.
Running the forge lint
command picks up these required scopes.
Add @forge/ui-jira
to your app's dependencies by running this command in the root directory of
your app:
1 2npm install @forge/ui-jira
Here's an example that updates an issue property based on the current value stored in the property.
1 2import ForgeUI, { render, IssuePanel, Text, Button } from '@forge/ui'; import { useIssueProperty } from '@forge/ui-jira'; const App = () => { const [count, setCount] = useIssueProperty('counter', 1); return ( <IssuePanel> <Text>Current value {count}</Text> <Button text="Add one (modify)" onClick={async () => { await setCount(count + 1); }} /> </IssuePanel> ); }; export const run = render(<App />);
forge-${key}.
This hook reads, writes, or updates the space properties in the Confluence page where the app is installed.
When using this event, your Forge app must have permission from the site admin to access the data it provides within the event payload. The OAuth scope required is documented under each product event.
Running the forge lint
command picks up these required scopes.
You'll need to add the @forge/ui-confluence
to your app's dependencies (0.2.5+). Run this command
in the directory:
1 2npm install @forge/ui-confluence
Here is an example of an app that stores information in a space property with useSpaceProperty
.
1 2import ForgeUI, { Button, Macro, render } from '@forge/ui'; import { useSpaceProperty } from '@forge/ui-confluence'; const App = () => { const [count, setCount] = useSpaceProperty('space-wide-count', 0); return ( <Button text={`Count is ${count}`} onClick={async () => { // replace current value (regardless of if changed by someone else) await setCount(count + 1); }} /> ); }; export const run = render(<Macro app={<App />} />);
Here's another example that updates the space property based on the current value stored in the property.
1 2import ForgeUI, { Button, Macro, render } from '@forge/ui'; import { useSpaceProperty } from '@forge/ui-confluence'; const App = () => { const [count, setCount] = useSpaceProperty('space-wide-count', 0); return ( <Button text={`Count is ${count}`} onClick={async () => { // update current value (avoids overwriting someone else's change) await setCount((prevCount) => prevCount + 1); }} /> ); }; export const run = render(<Macro app={<App />} />);
1 2function useSpaceProperty<V>( key: string, defaultValue: V ): [ V, ((value: V | ((prevValue: V) => V), retries?: number) => Promise<V>), () => Promise<void> ];
key: The key for the space property. The key is namespaced automatically and stored with a
key which has the format, forge-${key}
.
defaultValue: The default value to use if the space property does not exist yet.
Rate this page: