Skip to Content
UI ProtocolAppClientAdvanced Usage

Advanced Usage

This section covers more advanced topics and usage scenarios for the @akinon/app-client library. These techniques can help you build more complex and feature-rich applications within the Akinon UI Protocol ecosystem.

Custom Action Invocation

The invokeAction method allows you to execute custom actions defined in the app shell. This can be useful for performing operations that require coordination between multiple micro-frontends or accessing shared functionality.

import React from 'react'; import { useAppClient } from '@akinon/app-client'; const CustomActionComponent = () => { const { invokeAction } = useAppClient(); const handleCustomAction = async () => { try { const result = await invokeAction('customActionName', arg1, arg2); console.log('Custom action result:', result); } catch (error) { console.error('Custom action failed:', error); } }; return <button onClick={handleCustomAction}>Invoke Custom Action</button>; };

Rich Modal Integration

The showRichModal function allows you to display complex modal content, potentially loading another micro-frontend within the modal.

import React from 'react'; import { useAppClient } from '@akinon/app-client'; const RichModalButton = () => { const { showRichModal } = useAppClient(); const openRichModal = () => { /** * Displays a rich-contentful modal with the specified path and context. * This method communicates with the AppShell to display the complicated modals. * * @param {string} path - The path of displayed iframe. It must be a page path on the same client. * @param {unknown} context - Optional context. Its type must follow the rules: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm * @param {Object} size - Optional size of the modal. * @param {number | string} size.maxWidth - The maximum width of the modal. If falsish, the modal will be max 540px wide. * @param {number | string} size.maxHeight - The maximum height of the modal. If falsish, the modal will be max 360px high. * @param {string} closeIconColor - Optional color of the close icon. */ showRichModal( '/path-to-modal-content', { someContext: 'value' }, { maxWidth: 1000, maxHeight: 1000 }, '#000' ); }; return <button onClick={openRichModal}>Open Rich Modal</button>; };

The page rendered in the rich modal gets the

modalContext data via the useAppClient hook.

// Page to be rendered in rich modal const { modalContext } = useAppClient(); ... console.log(someContext); // { someContext: 'value' }

In addition to the above implementations, an example of the implementation that needs to be done in the container application is given below.

const richModalRef = useRef(); ... const actions = { ... showRichModal: ( uuid: string, path: string, modalContext: unknown, size: ApplicationModalSize, ) => { richModalRef.current.show({ uuid, path, size, }); }, }; ... <AppShellProvider apps={...} data={...} navigation={...} actions={actions} > {children} <RichModal richModalRef={richModalRef} /> </AppShellProvider> ... const RichModal = ({ richModalRef }) => { const [open, setOpen] = useState(false); const [uuid, setUuid] = useState(""); const [path, setPath] = useState(""); const [size, setSize] = useState<ApplicationModalSize>({}); useImperativeHandle( richModalRef, () => ({ show, close, }), [], ); const show = ({ uuid, path, size, }: { uuid: string; path: string; size: ApplicationModalSize; }) => { setOpen(true); setUuid(uuid); setPath(path); setSize(size); }; const close = () => { setOpen(false); setUuid(""); setPath(""); setSize({}); }; return ( <Modal open={open} onCancel={close} footer={null} width={size.maxWidth}> <ModalRenderer path={path} uuid={uuid} size={size} /> </Modal> ); };

Handling Application Data and Parameters

The useAppClient hook provides access to shared application data and parameters. You can use these to synchronize state across different parts of your application or respond to changes in the global context.

import React, { useEffect } from 'react'; import { useAppClient } from '@akinon/app-client'; const DataAwareComponent = () => { const { data, params, isLoading } = useAppClient(); useEffect(() => { if (!isLoading) { console.log('Application data:', data); console.log('Application parameters:', params); } }, [data, params, isLoading]); if (isLoading) { return <div>Loading...</div>; } return <div>Data-aware component content</div>; };

TypeScript Integration

When using TypeScript, you can create custom types for your application data and parameters to ensure type safety throughout your application.

import { useAppClient } from '@akinon/app-client'; interface MyAppData { user: { id: string; name: string; }; settings: { theme: 'light' | 'dark'; }; } interface MyAppParams { currentPage: string; } const TypedComponent = () => { const { data, params } = useAppClient<MyAppData, MyAppParams>(); // Now 'data' and 'params' are properly typed console.log(data?.user.name); console.log(params?.currentPage); return <div>Typed component content</div>; };

Error Handling and Logging

Implement robust error handling and logging to manage issues that may arise during action invocation or navigation.

import React from 'react'; import { useAppClient } from '@akinon/app-client'; const ErrorAwareComponent = () => { const { invokeAction, showErrorMessage } = useAppClient(); const handleRiskyAction = async () => { try { await invokeAction('riskyAction'); } catch (error) { console.error('Risky action failed:', error); showErrorMessage( 'Action Failed', 'The risky action could not be completed. Please try again later.' ); } }; return <button onClick={handleRiskyAction}>Perform Risky Action</button>; };

Performance Optimization

When working with large applications or complex data structures, consider using memoization techniques to optimize performance.

import React, { useMemo } from 'react'; import { useAppClient } from '@akinon/app-client'; const PerformanceOptimizedComponent = () => { const { data } = useAppClient(); const processedData = useMemo(() => { // Perform expensive computation here return someExpensiveOperation(data); }, [data]); return <div>Processed data: {processedData}</div>; };

By leveraging these advanced techniques, you can create more sophisticated and efficient applications using the @akinon/app-client library within the Akinon UI Protocol ecosystem.