Rate this page:

Forge UI hooks

Forge UI Hooks are functions that let you manage app state and do things such as prefetching data to render your app. The useState and useAction hooks add and update local state, while the useProductContext hook is for reading the context information about where the app is running.

useState

This hook adds and updates local state to a component.

Usage

Here is an example of useState to create a counter app.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import 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 />} />);

Function signature

1
2
3
function useState<V>(
  initialValue: V | (() => V) | (() => Promise<V>)
): [V, (newState: V) => void];

Arguments

  • initialValue: The initial state of the hook. This can be a value, a function that returns a value or a function that returns a Promise. If a Promise is returned, the resolved value of the Promise is the initial state.

Returns

  • An array of two elements. The first element is the current state of the hook. The second value is a function used to update the state. The argument of this function is the value of the new state.

useAction

This hook manages local state in a similar way to the useState hook, providing a more complex reducer argument to update state.

Usage

Here is an example of useAction to create a counter app.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import 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 />} />);

Function signature

1
2
3
4
function useAction<V, P>(
  reducer: (currentState: V, payload: P) => V | Promise<V>,
  initialValue: V | (() => V) | (() => Promise<V>)
): [V, (payload?: P) => void];

Arguments

  • reducer: A function that describes how to update the state. The reducer gets passed the current state and the payload. The value returned by this function becomes the new state. If a Promise is returned by the reducer, the resolved value of the Promise is the new state.
    • currentState: The current value of the hook.
    • payload: The data that the function used to update the state was called with.
  • initialValue: The initial state of the hook. This can be a value, a function that returns a value or a function that returns a Promise. If a Promise is returned, the resolved value of the Promise is the initial state.

Returns

  • An array of two elements. The first element is the current state of the hook. The second value is a function used to update the state. The arguments you call this function with will be passed to the second argument of the reducer function.

useProductContext

This hook reads the context in which the component is currently running.

Usage

Here is an example of an app that displays all its context information with useProductContext.

1
2
3
4
5
6
7
8
9
10
import ForgeUI, { useProductContext, Text, Macro, render } from '@forge/ui';

const App = () => {
  const context = useProductContext();
  return (
    <Text content={`All info about my context: ${JSON.stringify(context)}`} />
  );
};

export const run = render(<Macro app={<App />} />);

Function signature

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
interface ProductContext {
  accountId?: string;
  cloudId?: string;
  contentId?: string;
  localId?: string;
  spaceKey?: string;
  installContext?: string;
  platformContext?: PlatformContext;
  extensionContext?: ExtensionContext;
}

interface PlatformContext {
  type: string;
}

interface JiraContext extends PlatformContext {
  type: 'jira';
  issueId: number;
  issueKey: string;
  issueType: string;
  projectId: string;
  projectKey: string;
}

interface ExtensionContext {
  type: string;
}

interface ContextMenuExtensionContext extends ExtensionContext {
  type: 'contextMenu';
  selectedText: string;
}

function useProductContext(): ProductContext;

Returns

  • 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.
    • accountId: The Atlassian ID of the user that interacted with the component.
    • contentId: The id of the piece of content in which this component appears.
    • localId: A unique id for this instance of this component in the content.
    • spaceKey: The space in which the content is located (Confluence only).
    • installContext: The ari identifying the cloud / product context of this component installation.
    • platformContext: Contextual information about the current environment that depends on where the component is being used (currently, Jira only).
    • extensionContext: Contextual information about the current environment that depends on the extension being used.
  • JiraContext: Contextual information returned when the component is running in Jira.
    • type: The product type (always 'jira').
    • issueId: The ID of the issue that the component is on.
    • issueKey: The key of the issue that the component is on.
    • issueType: The type of issue that the component is on.
    • projectKey: The key of the project that the component is on.
    • projectId: The ID of the project that the component is on.
  • ContextMenuExtensionContext: Contextual information returned by the confluence:contextMenu extension point.

    • type: The extension type (always 'contextMenu').
    • selectedText: The selected text on the Confluence page or blog.

useConfig

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 modify the values.

Usage

Here is an example of accessing configuration for a Forge macro.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const App = () => {
  // Retrieve the configuration
  const config = useConfig();

  // Use the configuration values
  return <Text content={`${config.name} is ${config.age} years old.`} />;
};

// Function that defines the configuration UI
const Config = () => {
  return (
    <ConfigForm>
      <TextField name="name" label="Pet name" />
      <TextField name="age" label="Pet age" />
    </ConfigForm>
  );
};

// A macro containing props for the app code, configuration,
// and default configuration values.
export const run = render(
  <Macro
    app={<App />}
    config={<Config />}
    defaultConfig={{
      name: "Unnamed Pet",
      age: "0"
    }}
  />
);

Function Signature

1
2
3
4
5
interface ExtensionConfiguration {
  [key: string]: any;
}

function useConfig(): ExtensionConfiguration;

Arguments

None

Returns

  • ExtensionConfiguration: A dictionary containing the configuration key-value pairs. The keys are the names of the components in the ConfigForm.

useContentProperty

This hook reads, writes, or updates the content properties in the Confluence page where the app is installed.

Usage

You'll need to add the @forge/ui-confluence to your app’s dependencies. Run this command in the directory:

1
npm install @forge/ui-confluence

Here is an example of an app that stores information in a content property with useContentProperty.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import 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 />} />);

Function signature

1
2
3
4
5
6
7
8
function useContentProperty<V>(
  key: string,
  defaultValue: V
): [
  V,
  ((value: V | ((prevValue: V) => V), retries?: number) => Promise<V>),
  () => Promise<void>
];

Arguments

  • key: The key for the content prop. The key is namespaced automatically and stored with a key of form forge-${localId}-${key}.
  • defaultValue: The default value to use if the content property does not exist yet.

Returns

  • An array of three elements.
    • The first element is the current value of the content property (or default value if the content property does not exist).
    • The second value is a function used to update the content property. There are two ways to use this:
      • Provide a new value, which will create or replace the content property
      • Provide an updater function, which takes the current value stored in the content property and returns an updated value to store. The update may be called multiple times per function call if the update fails (due to other updates). A second value is optional (defaults to 2) to specify the number of retries to attempt.
    • The third value is a function used to delete the content property.

useIssueProperty

This hook reads, writes, or updates the issue properties for the Jira issue that the component is on.

Usage

Add @forge/ui-jira to your app’s dependencies by running this command in the root directory of your app:

1
npm install @forge/ui-jira

Here’s an example that updates an issue property based on the current value stored in the property.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import Forge, {
  render,
  IssuePanel,
  Text,
  Button,
} from '@forge/ui';
import { useIssueProperty } from '@forge/ui-jira';
const App = () => {
  const [count, setCount] = useIssueProperty("counter", 1);
  return (
    <IssuePanel>
      <Text content={`Current value ${count}`} />
      <Button
        text="Add one (modify)"
        onClick={() => {
          setCount(count + 1);
        }}
      />
    </IssuePanel>
  );
};
export const run = render(<App />);

Arguments

  • key: The key for the issue 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 issue property does not exist yet.

Returns

  • An array of three elements:
    • The first element is the current value of the issue property. If the issue property does not exist, this element will be the default value.
    • The second element is a function used to update the issue property, which is used in two ways:
      • Provides a new value that creates or replaces the issue property.
      • Provides an updater function that takes the current value stored in the issue property and returns an updated value to store. The update may be called multiple times per function call if the update fails (for example, due to other updates). A second value is optional (defaults to 2) and specifies the number of retries to attempt.
    • The third element is a function used to delete the issue property.

Rate this page: