p-mazhnik / flutter-embedding

Contains examples of embedding Flutter in React apps.
https://p-mazhnik.github.io/flutter-embedding/expo/
23 stars 5 forks source link

Cannot read properties of null (reading 'loader') #13

Closed yaduatdataspot closed 2 months ago

yaduatdataspot commented 3 months ago

ERROR Cannot read properties of null (reading 'loader') TypeError: Cannot read properties of null (reading 'loader') at engineInitializer ### (http://localhost:3001/static/js/bundle.js:589:18) at new Promise () at initFlutterApp (http://localhost:3001/static/js/bundle.js:587:39) at http://localhost:3001/static/js/bundle.js:604:5 at commitHookEffectListMount (http://localhost:3001/static/js/bundle.js:50432:30) at commitPassiveMountOnFiber (http://localhost:3001/static/js/bundle.js:51925:17) at commitPassiveMountEffects_complete (http://localhost:3001/static/js/bundle.js:51897:13) at commitPassiveMountEffects_begin (http://localhost:3001/static/js/bundle.js:51887:11) at commitPassiveMountEffects (http://localhost:3001/static/js/bundle.js:51877:7) at flushPassiveEffectsImpl (http://localhost:3001/static/js/bundle.js:53760:7)

Screenshot 2024-06-18 at 5 03 55 PM

@p-mazhnik getting this error while running npm run start, iam new to react and the code is working fine in type script , getting this error only when i convert flutterview.tsx in to flutterview.jsx . i have mentioned the FlutterView.jsx code sample below please take a look at it

import React, { useEffect, useRef, memo } from 'react'
import CircularProgress from '@mui/material/CircularProgress'
import Box from '@mui/material/Box'

// Assuming the global _flutter namespace exists
let _flutter = null; 
// declare var _flutter: any;

const divStyle = {
  height: '100%',
  width: '100%',
}

const FlutterView = memo(({
  assetBase = '',
  src = 'main.dart.js',
  onClicksChange,
  onScreenChange,
  onTextChange,
  text,
  screen,
  clicks,
}) => {
  const flutterState = useRef(null)
  const ref = useRef(null)

  const onFlutterAppLoaded = (state) => {
    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((resolve) => {
        console.log('setup Flutter engine initializer...')
        _flutter.loader.loadEntrypoint({
          entrypointUrl: src,
          onEntrypointLoaded: resolve,
        })
      })
      if (!isRendered) return

      console.log('initialize Flutter engine...')
      const appRunner = await engineInitializer?.initializeEngine({
        hostElement: target,
        assetBase: assetBase,
      })
      if (!isRendered) return

      console.log('run Flutter engine...')
      await appRunner?.runApp()
    }
    initFlutterApp()

    const eventListener = (event) => {
      let state = event.detail
      onFlutterAppLoaded(state)
    }

    target?.addEventListener('flutter-initialized', eventListener, {
      once: true,
    })

    return () => {
      isRendered = false
      target?.removeEventListener('flutter-initialized', eventListener)
    }
  }, [])

  useEffect(() => {
    flutterState.current?.setText(text)
  }, [text])

  useEffect(() => {
    flutterState.current?.setScreen(screen)
  }, [screen])

  useEffect(() => {
    flutterState.current?.setClicks(clicks)
  }, [clicks])

  return (
    <div
      ref={ref}
      style={divStyle}
    >
      <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%' }}>
        <CircularProgress/>
      </Box>
    </div>
  )
})

export default FlutterView
p-mazhnik commented 2 months ago

Hi! You have let _flutter = null; line in your code, which overrides the _flutter variable from the global scope.
Therefore, _flutter.loader = null.loader, and that is why you got the error Cannot read properties of null (reading 'loader') You don't need this line

yaduatdataspot commented 2 months ago

Hi! You have let _flutter = null; line in your code, which overrides the _flutter variable from the global scope. Therefore, _flutter.loader = null.loader, and that is why you got the error Cannot read properties of null (reading 'loader') You don't need this line

hey @p-mazhnik thanks for replying , i removed let _flutter = null; and run npm run start command then my flutter app is visible on recat app but i get an error

Failed to compile.

[eslint] src/App/FlutterView/FlutterView.jsx Line 46:9: '_flutter' is not defined no-undef

Search for the keywords to learn more about each error. WARNING in [eslint] src/App/FlutterView/FlutterView.jsx Line 78:6: React Hook useEffect has missing dependencies: 'assetBase', 'onFlutterAppLoaded', and 'src'. Either include them or remove the dependency array react-hooks/exhaustive-deps

ERROR in [eslint] src/App/FlutterView/FlutterView.jsx Line 46:9: '_flutter' is not defined no-undef

Search for the keywords to learn more about each error.

webpack compiled with 1 error and 1 warning

Screenshot 2024-06-19 at 4 47 19 PM

so do i need to declare _flutter variable globaly , how to solve this issue

p-mazhnik commented 2 months ago

Have you added the flutter js script? https://github.com/p-mazhnik/flutter-embedding/blob/843f008c25794b1ada94ada07e0a0a0e7687d9ae/cra-flutter/public/index.html#L19

yaduatdataspot commented 2 months ago

Have you added the flutter js script?

https://github.com/p-mazhnik/flutter-embedding/blob/843f008c25794b1ada94ada07e0a0a0e7687d9ae/cra-flutter/public/index.html#L19

@p-mazhnik Yes I already add this line in my index.html file under the public folder

p-mazhnik commented 2 months ago

Actually, it looks like eslint problem. You can try to configure it for _flutter global variable: https://eslint.org/docs/latest/use/configure/language-options#specifying-globals

Should be smth like /* global _flutter */ at the top of the js file.

Or you can try to ignore eslint rule for the line:

+ // eslint-disable-next-line
_flutter.loader.loadEntrypoint({
    entrypointUrl: src,
    onEntrypointLoaded: resolve,
  })
yaduatdataspot commented 2 months ago

Actually, it looks like eslint problem. You can try to configure it for _flutter global variable: https://eslint.org/docs/latest/use/configure/language-options#specifying-globals

Should be smth like /* global _flutter */ at the top of the js file.

Or you can try to ignore eslint rule for the line:

+ // eslint-disable-next-line
_flutter.loader.loadEntrypoint({
    entrypointUrl: src,
    onEntrypointLoaded: resolve,
  })

It is working thanks for your valuable time