-1

I try to implement a modal from materializecss into my react app:

const ModalCardMetrics = (props) => {
    let modalInstance;
    let modalBox = useRef();

  useEffect(()=>{
        modalInstance = window.M.Modal.init(modalBox.current, {})[0];
   },[])

 const openModal = ()=>{
        modalInstance.open();  // modalInstance is undefined?!
 }
 return (
        <div>
          <div rel={modalBox}>...modalbox...</div>
          <button onClick={openModal}>Menu</button>
        </div>
   )
}

Uncaught TypeError: modalInstance is undefined toggleModal ModalCardMetrics.js:90 React 14

In this codesandbox you see that my approach would work - I assume: I am using a cdn (in index.html) to load Materializecss and in the codesandbox it is done with the npm package and import. https://codesandbox.io/s/quiet-platform-ph8g6

Suisse
  • 3,467
  • 5
  • 36
  • 59
  • 1
    Does this answer your question? [Updating a JSX Variable with useEffect "lost after each rerender" Issue](https://stackoverflow.com/questions/60784899/updating-a-jsx-variable-with-useeffect-lost-after-each-rerender-issue) – pilchard Jul 22 '21 at 22:00
  • @pilchard partly; because I still don't know how to access modalInstance. What is the right way? - and also if it rerenders than the useEffect will be called again, and then modalInstance should be set again and not be undefined? – Suisse Jul 22 '21 at 22:03
  • You've passed an empty dependency array to the useEffect causing it to only run on the first render at which point it assigns a value to `modalInstance`. On the next render, the variable is redeclared and the useEffect doesn't run again. To persist values across renders you need to implement either state or a ref value. Read the docs and then come back and ask more. [React: State and Lifecyle](https://reactjs.org/docs/state-and-lifecycle.html) – pilchard Jul 22 '21 at 22:10
  • I already read that. I still don't get it at which time I can access the dom. Before I used class components and there I used componentDidMount(); - and I also already had tried to solve this which const [modalInstance, setModalInstance] = useState(); but still, when do I access the DOM and set my modalInstance with setModalInstance()? – Suisse Jul 22 '21 at 22:26
  • By the time `useEffect` runs the DOM is available (and your ref will hold a reference to the relevant element once you fix your typo). By passing an empty dependency array your `useEffect` is fulfilling the function of `componentDidMount()` as it won't run on successive renders. You might want to look at [react-materialize](http://react-materialize.github.io/react-materialize/?path=/story/react-materialize--welcome) – pilchard Jul 22 '21 at 22:31
  • As you see here in the modified version from @squish the same code I have is working perfectly... so the useEffect is not really reSeting the `modalInstance` https://codesandbox.io/s/quiet-platform-ph8g6 – Suisse Jul 22 '21 at 22:41
  • It is only working because nothing else is currently causing the component to rerender, as soon as something does, the variable will be redeclared and your modal will break. The main problem with using the modal this way is it is bypassing the React lifecycle to render the modal. – pilchard Jul 22 '21 at 22:52
  • Thank you very much for explaining this. Now its more clear. I did the workaround with setting the ref inside the state, but the best would be to use the react-materialize. Have a good life. – Suisse Jul 22 '21 at 22:58

2 Answers2

0

You need to use useState in functional react

const ModalCardMetrics = (props) => {
    const [modalInstance, setModalInstance] = useState();
    let modalBox = useRef();

    useEffect(()=>{
        setModalInstance(window.M.Modal.init(modalBox.current, {})[0]);
     },[])

   const openModal = ()=>modalInstance.open();
   return (
        <div>
          <div rel={modalBox}>...modalbox...</div>
          <button onClick={openModal}>Menu</button>
        </div>
   )
}

Also, don't forget to import useState import {useState} from 'react'

-2

Here is a working sandbox, kinda: https://codesandbox.io/s/immutable-sea-bvuw4?file=/src/Modal.js

You needed to change rel={modalBox}

<div rel={modalBox}>...modalbox...</div>

To

<div ref={modalBox}>...modalbox...</div>
squish
  • 846
  • 12
  • 24
  • check your post please. Here is a modified version of yours: https://codesandbox.io/s/quiet-platform-ph8g6 – Suisse Jul 22 '21 at 22:42