Hi there,
I’m refactoring a plugin to use UI Kit 2. It parses a download link from a textfield given by the user, fetches the response, formats it and embeds it into the confluence page.
Frontend js:
import React, { Fragment, useEffect, useState } from 'react';
import ForgeReconciler, { Label, Text, useConfig, SectionMessage, Textfield, Link } from '@forge/react';
import { invoke } from '@forge/bridge';
const App = () => {
const [htmlValue, sethtmlValue] = useState({ body: '', status: '' });
const config = useConfig();
if (!config) {
return (
<SectionMessage title="You need to configure this macro" appearance="warning">
<Text>
While editing the page, select the macro, and click on the pencil icon
to display configuration options.
</Text>
</SectionMessage>
);
}
console.log("Config: ", config?.path);
const url_config = config?.path;
console.log("Url config: ", url_config);
useEffect(() => {
console.log("✅ Passing path to invoke:", { path: url_config });
invoke('fetch', { path: url_config })
.then((response) => {
console.log("Response: ", response);
sethtmlValue({ body: response.body, status: response.status });
});
}, []);
console.log(htmlValue.body);
console.log(htmlValue.status);
if (htmlValue.status != 200)
return (
<Text>n/a</Text>
)
if(htmlValue?.body) {
var buildNumber;
const buildNumberRe = /<p>(\d+)<\/p>/.exec(htmlValue.body);
if (buildNumberRe != null)
buildNumber = <Text>{buildNumberRe[1]}</Text>;
const hashRe = /<p><small>(\w+)<\/small><\/p>/.exec(htmlValue.body);
var hash;
if (hashRe != null)
hash = <Text>{hashRe[1]}</Text>;
return (
<Text>
<Fragment>
{buildNumber ? buildNumber : "Loading..."}
{hash ? hash : "Loading..."}
</Fragment>
</Text>
);
};
};
const ConfigEmbed = () => {
return (
<>
<Label>Path to file in bucket</Label>
<Textfield name="path" />
</>
);
};
ForgeReconciler.addConfig(<ConfigEmbed />);
ForgeReconciler.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
Backend resolver:
import Resolver from '@forge/resolver';
import { fetch } from '@forge/api';
const resolver = new Resolver();
resolver.define('fetch', async (req) => {
try {
const prefix = "https://supersecret.url";
const path = await req.payload.path;
console.log(path);
const secret = process.env.SECRET;
const url = prefix + path + "?" + secret;
const result = await fetch(url);
console.log('Fetch result:', result);
const body = await result.text();
const status = result.status;
console.log('Body: ', body);
console.log('Status: ', status);
return { body, status };
} catch (error) {
console.error('Error in fetch:', error);
throw error; // Re-throw to propagate the error
}
});
export const handler = resolver.getDefinitions();
If I harcode the given path to url_config, it works and it fetches the url correctly.
When I add the Config textbox to the code, it crashes at the useEffect function with this error: Minified React error #310 – React
console.log shows the correct url_config variable right before crashing.
Any ideas what I’m doing wrong?
Thanks for the help in advance!