Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ploblem on reRender on REACTJS #140

Open
epsilon11101 opened this issue Jul 13, 2023 · 3 comments
Open

Ploblem on reRender on REACTJS #140

epsilon11101 opened this issue Jul 13, 2023 · 3 comments

Comments

@epsilon11101
Copy link

epsilon11101 commented Jul 13, 2023

each time that i want to re render a new component the component is appended on wrapper container

i use this when i want to re render other component maybe you can implement the code to validate is there are code on the main wrapper

     const hasChildren = h5pRef.current.children;
      if (hasChildren.length !== 0) {
        const parent = hasChildren[0].parentNode;
        parent.removeChild(hasChildren[0]);
      }

to understand you can see my own code:

App.jsx:

import Game from "./components/Game";
import { useEffect, useState } from "react";

const App = () => {
  const [currentGame, setCurrentGame] = useState(0);

  const games = ["cuestionario", "h5p-folder"];

  const showNewGameHandler = () => {
    if (currentGame <= 1) {
      setCurrentGame(currentGame + 1);
    } else {
      setCurrentGame(0);
      window.location.reload();
    }
  };

  return (
    <>
      <Game name={games[currentGame]} id={currentGame} />
      <button onClick={showNewGameHandler}>siguiente</button>
    </>
  );
};

export default App;

GameComponent

import { useEffect, useRef } from "react";
import { H5P as H5PStandalone } from "h5p-standalone";

const Game = ({ name, id }) => {
  let firstTime = true;
  const componentConfig = {
    h5pJsonPath: `/${name}`,
    frameJs: "/assets/frame.bundle.js",
    frameCss: "/assets/styles/h5p.css",
  };

  const h5pRef = useRef(null);

  const loadH5PComponent = async () => {
    if (h5pRef.current) {
      await new H5PStandalone(h5pRef.current, componentConfig);

      window.H5P.externalDispatcher.on("xAPI", (event) => {
        //do something useful with the event
        console.log("results:", event.getScore(), "---->", name);
      });
    }
  };

  useEffect(() => {
    if (firstTime) {
      const hasChildren = h5pRef.current.children;
      if (hasChildren.length !== 0) {
        const parent = hasChildren[0].parentNode;
        parent.removeChild(hasChildren[0]);
      }

      loadH5PComponent();
      firstTime = false;
    }
  }, [name]);

  return <div id={`h5p-container-${id}`} ref={h5pRef} />;
};

export default Game;

Maybe yo can implement this solution as below

File: h5p-standalon.ts
Method : renderPLayerFrame
line: 131 apox

suggested code:

    if (params.embedType === "iframe") {
      const divWrapper = document.getElementsByClassName("h5p-iframe-wrapper");
      if (divWrapper.length !== 0) {
        const parentWrapper = divWrapper[0].parentNode;
        parentWrapper.removeChild(divWrapper[0]);
      }

@DiegoGonzalezCruz
Copy link

Dear @epsilon11101 you are my hero, thanks I had my component being wrongly duplicated and your code helped me a lot! Kudos for you!

@DiegoGonzalezCruz
Copy link

Sure, happy to help!

import { useEffect, useMemo, useState } from 'react'
import { Loading } from '../../../Animations/Loading'
import { completeH5PTopic } from '../../../../lib/sinapsis/gamification'
import { useSession } from 'next-auth/react' // ES6
import ToastGamification from '../../../Notificaciones/ToastGamification'
import { toast } from 'react-hot-toast'
import { useRef } from 'react'

const POINTS_PER_TOPIC_COMPLETED = 5

const H5PContainer = ({ location, course, topic }) => {
  const H5PStandalone = useMemo(() => require('h5p-standalone').H5P, [])

  const [isLoaderVisible, setIsLoaderVisible] = useState(true)

  let firstTime = true
  const h5pPath = `https://mycdn.com/h5p-v1/${location}`
  const { data } = useSession()
  const user = data?.user
  // console.log(user, 'user')
  const name = ''
  const options = {
    h5pJsonPath: h5pPath,
    frameJs: '/h5p/dist/frame.bundle.js',
    frameCss: '/h5p/dist/styles/h5p.css',
  }
  const h5pRef = useRef(null)

  // console.log('H5PStandalone', H5PStandalone)
  const loadH5PComponent = async () => {
    if (h5pRef.current && window) {
      await new H5PStandalone(h5pRef.current, options)
      setIsLoaderVisible(false)

      window.H5P.externalDispatcher.on('xAPI', (event) => {
        //do something useful with the event
        // console.log(event, 'event')
        // console.log('results:', event.getScore(), '---->', name)
        if (
          event.getScore() > 1 ||
          event.data.statement.verb.display['en-US'] === 'completed'
        ) {
          fireCompleteH5PTopicFn(
            window.H5P,
            user?.id,
            course?.slug,
            topic?.slug,
          )
        }
      })
    }
  }
  useEffect(() => {
    if (firstTime) {
      const hasChildren = h5pRef.current.children
      if (hasChildren.length !== 0) {
        const parent = hasChildren[0].parentNode
        parent.removeChild(hasChildren[0])
      }

      loadH5PComponent()
      firstTime = false
      // setIsLoaderVisible(false)
    }
  }, [name])

  return (
    <div className="w-full h-full ">
      {isLoaderVisible && <Loading />}
      <div id={`h5p-container-${location}`} ref={h5pRef} />
    </div>
  )
}

export default H5PContainer

async function fireCompleteH5PTopicFn(userId, courseSlug, topic) {
  const res = await completeH5PTopic(userId, courseSlug, topic)
  toast.dismiss()
  if (res.status === 200) {
    toast.custom((t) => (
      <ToastGamification
        isVisible={t.visible}
        onDismiss={() => toast.dismiss(t.id)}
        points={POINTS_PER_TOPIC_COMPLETED}
      />
    ))
  }
  return true
}

@zuhrasofyan
Copy link

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants