I am trying to embed Flutterflow app in a React app which uses certain query parameters, I am getting errors while trying to render Flutter widgets as React components. Its working fine when there are no query parameters eg. xyz.com/ but doesn't work when its xyz.com?qp=123
This is the exact error i am getting:
ERROR
Exception: The base href has to end with a "/" to work correctly
Exception: The base href has to end with a "/" to work correctly at Object.f
(http://localhost:3000/flutter/main.dart.js:4974:19) at Object.ae
(http://localhost:3000/flutter/main.dart.js:4983:15) at http://localhost:3000/flutter/main.dart.js:9006:20 at aKV.a
(http://localhost:3000/flutter/main.dart.js:6303:63) at aKV.$2
(http://localhost:3000/flutter/main.dart.js:40625:14) at Object.R
(http://localhost:3000/flutter/main.dart.js:6289:10) at Object.aLH
(http://localhost:3000/flutter/main.dart.js:9033:10) at aLJ.$0
(http://localhost:3000/flutter/main.dart.js:81607:15) at http://localhost:3000/flutter/main.dart.js:44865:12 at aKV.a
(http://localhost:3000/flutter/main.dart.js:6303:63)
Note: When I am embedding a normal flutter app using the same method, its working fine but this is happening specifically with flutterflow apps.
How I am trying to embed?
This is my prebuild npm script:
"prebuild": "cd embedding_test && flutter clean && flutter build web --output=../public/flutter && cd -",
I have placed the app created by flutterflow at the root of my react app, then ran this command. The component that reads the main.dart.js and renders the app has the logic as below:
export const FlutterView: React.FC<FlutterViewProps> = memo(
({
assetBase = "",
src = "main.dart.js",
onClicksChange,
onScreenChange,
onTextChange,
text,
screen,
clicks,
}) => {
const flutterState = useRef<any>(null);
const ref = useRef<HTMLDivElement>(null);
const onFlutterAppLoaded = (state: any) => {
flutterState.current = state;
// listen to state changes
state.onClicksChanged(onClicksChange);
state.onTextChanged(onTextChange);
state.onScreenChanged(onScreenChange);
// set initial values
state.setText(text);
state.setScreen(screen);
state.setClicks(clicks);
};
useEffect(() => {
const target = ref.current;
let isRendered = true;
const initFlutterApp = async () => {
if (!isRendered) return;
const engineInitializer = await new Promise<any>((resolve) => {
_flutter.loader.loadEntrypoint({
entrypointUrl: src,
onEntrypointLoaded: resolve,
});
});
if (!isRendered) return;
const appRunner = await engineInitializer?.initializeEngine({
hostElement: target,
assetBase: assetBase,
});
if (!isRendered) return;
await appRunner?.runApp();
};
initFlutterApp();
const eventListener = (event: Event) => {
let state = (event as CustomEvent).detail;
onFlutterAppLoaded(state);
};
target?.addEventListener("flutter-initialized", eventListener, {
once: true,
});
return () => {
isRendered = false;
target?.removeEventListener("flutter-initialized", eventListener);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
flutterState.current?.setText(text);
}, [text]);
useEffect(() => {
flutterState.current?.setScreen(screen);
}, [screen]);
useEffect(() => {
flutterState.current?.setClicks(clicks);
}, [clicks]);
return (
<div className="flutter-view" ref={ref} style={divStyle}>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "center",
height: "100%",
}}
>
<CircularProgress />
</Box>
</div>
);
}
);