So, I've got a variable dog that I want to persist between re-renders.
const { useState, useEffect, useRef } = React;
class Animal {
constructor(name) {
this.name = name;
}
greet() {
alert(`Hello I'm ${this.name}!`);
}
}
const Dog = () => {
let dog;
useEffect(() => {
dog = new Animal("Rusty", 5);
}, []);
return <button onClick={() => dog.greet()}>Greet</button>;
};
const App = () => {
const [num, setNum] = useState(1);
return (
<main>
<p>{num}</p>
<button onClick={() => setNum(num + 1)}>Add 1</button>
<br />
<Dog />
</main>
);
};
ReactDOM.render(<App />, document.querySelector("#react-container"));
<div id="react-container"></div>
<script src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
In the snippet above there's the dog variable that I want to persist between re-renders. On the first render Dog component works fine and the alert is triggered successfully on clicking the Greet button.
But once there's a re-render which can be forced by clicking the Add 1 button, the dog variable is reset and now there's no greet method on it, so clicking Greet button throws an error.
I fixed this by using the useRef hook, just wanted to know if there's some better alternative or useRef is the best practice here.
So, I modified the Dog component to the following:
const Dog = () => {
let dog = useRef(null);
useEffect(() => {
dog.current = new Animal("Rusty", 5);
}, []);
return <button onClick={() => dog.current.greet()}>Greet</button>;
};
const { useState, useEffect, useRef } = React;
class Animal {
constructor(name) {
this.name = name;
}
greet() {
alert(`Hello I'm ${this.name}!`);
}
}
const Dog = () => {
let dog = useRef(null);
useEffect(() => {
dog.current = new Animal("Rusty", 5);
}, []);
return <button onClick={() => dog.current.greet()}>Greet</button>;
};
const App = () => {
const [num, setNum] = useState(1);
return (
<main>
<p>{num}</p>
<button onClick={() => setNum(num + 1)}>Add 1</button>
<br />
<Dog />
</main>
);
};
ReactDOM.render(<App />, document.querySelector("#react-container"));
<div id="react-container"></div>
<script src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>