This page is for Web engineers who want to integrate an existing flow into their product.
These instructions presume you’re using React.
Install react, the design system component and styling packages, and the Dynamic Flow client.
# pnpm
pnpm add react react-dom react-intl
pnpm add @transferwise/components @transferwise/icons @transferwise/neptune-css @wise/components-theming @wise/art @transferwise/formatting
pnpm add @wise/dynamic-flow-client-internal
If you're using TypeScript, you might also want to install the types package, which contains:
- Types for all Dynamic Flow entities (useful when using
initialStep, or for writing mocks) - Zod validators
- Renderer Props, for writing custom renderers
pnpm add -D @wise/dynamic-flow-types
To get Dynamic Flow working, you’ll need to import the correct CSS files, prepare the translations using the user’s locale, and wrap the component in several providers.
For CRAB apps, use the getLocalisedMessages(...) function for translations
import "@transferwise/neptune-css/dist/css/neptune.css";
import "@transferwise/components/build/main.css";
import '@transferwise/icons/lib/styles/main.min.css';
import "@wise/dynamic-flow-client-internal/build/main.css";
import {
Provider,
SnackbarProvider,
translations as componentTranslations,
} from '@transferwise/components';
import { getLocalisedMessages } from '@transferwise/crab/client';
import { ThemeProvider } from "@wise/components-theming";
import { DynamicFlow, translations as dynamicFlowsTranslations } from '@wise/dynamic-flow-client-internal';
const App = () => {
const messages = getLocalisedMessages(locale, [componentTranslations, dynamicFlowsTranslations])
return (
<Provider i18n={{ locale, messages }}>
<ThemeProvider theme={theme} screenMode={screenMode}>
<SnackbarProvider>
<DynamicFlow {...props} />
</SnackbarProvider>
</ThemeProvider>
</Provider>
);
}
export default App;
You'll need to merge the '@transferwise/components' translations with the '@wise/dynamic-flow-client' translations.
import "@transferwise/neptune-css/dist/css/neptune.css";
import "@transferwise/components/build/main.css";
import '@transferwise/icons/lib/styles/main.min.css';
import "@wise/dynamic-flow-client-internal/build/main.css";
import {
Provider,
SnackbarProvider,
translations as componentTranslations,
} from '@transferwise/components';
import {
DynamicFlow,
translations as dynamicFlowTranslations,
} from '@wise/dynamic-flow-client-internal';
import { ThemeProvider } from "@wise/components-theming";
const App = () => {
// create your messages object
const messages: Record<string, string> = {
...(componentTranslations[lang] || componentTranslations[lang.replace('-', '_')] || componentTranslations[lang.substring(0, 2)] || {}),
...(dynamicFlowTranslations[lang] || dynamicFlowTranslations[lang.replace('-', '_')] || dynamicFlowTranslations[lang.substring(0, 2)] || {}),
}
return (
<Provider i18n={{ locale, messages }}>
<ThemeProvider theme={theme} screenMode={screenMode}>
<SnackbarProvider>
<DynamicFlow {...props} />
</SnackbarProvider>
</ThemeProvider>
</Provider>
);
}
export default App;
<DynamicFlow
flowId="my-flow"
customFetch={fetch}
initialAction={initialAction}
onComplete={(status, data) => console.log(status, data)}
/>
| Props | Required | Description |
|---|---|---|
flowId | Yes | Flow id used in events. |
customFetch | Yes | Custom fetch function that may add authentication headers to every request. |
initialAction | Yes* | Initial Action to execute to get the first step. *Not required if using initialStep. |
initialStep | Yes* | Initial Step. *Not required if using initialAction. |
renderers | No | A list of renderers to customise presentation with. See the custom rendering guide. |
onAnalytics | No | Callback that accepts eventName and possible data object. |
onComplete | Yes | Callback that accepts a status and possible data object. |
onError | No | Callback that accepts an error and possible status object. |
onEvent | No | Callback that accepts eventName and possible data object. |
Please, check the README.md.
You can provide additional renderers to utilise custom rendering. It is important that these are statically defined, or the component might be re-rendered continuously.
For example, instead of doing this:
<DynamicFlow
flowId="my-flow"
customFetch={fetch}
initialAction={initialAction}
renderers={[MyCustomRenderer]} // <-- ❌ Not statically defined, will create a new reference on every render
onComplete={(status, data) => console.log(status, data)}
/>
Do this:
const renderers = [MyCustomRenderer]; // <-- ✅ Statically defined, reference is stable across renders
const WrappingComponent = () => {
return (
<DynamicFlow
flowId="my-flow"
customFetch={fetch}
initialAction={initialAction}
renderers={renderers}
onComplete={(status, data) => console.log(status, data)}
/>
);
}