Using a stateful pattern, I usually initialize a kind of helper class in my constructor and consume its methods in some component lifecycle methods like below:
class StatefulComponent extends Component {
constructor(props) {
super(props);
this.helper = new HelperClass();
}
componentDidMount() {
this.helper.doSomething();
}
}
Now, I wanted to convert the same logic into a stateless function component like this:
const StatelessFunction = (props) => {
this.helper = new HelperClass();
useEffect(() => {
this.helper.doSomething();
}, []);
}
But I worried when I saw that this component is being called every prop change from the beginning. And this made me think that my class instance is being created over and over. Am I wrong? Is there anything I can do for preventing re-creation of my class and use a ref instead?
I came across useRef but not sure if it fits my case.
Looking back at this and some of the comments I can see that useMemo can not be trusted to not run the HelperClass constructor again and useRef will only set the helper after the first render because it's initial value can't be a function. Probably useState is the easiest and most reliable way to do this:
const [helper] = useState(()=>new HelperClass());
You can use useMemo to create an instance of HelperClass and useEffect to call it. Giving them both empty array of dependencies means they will only be called "on mount". I put on mount in quotes because memo will be called only on first render and effect will be called after first render cycle is finished.
const StatelessFunction = props => {
const helper = useMemo(() => new HelperClass(), []);
useEffect(() => {
helper.doSomething();
}, [helper]);
return (<JSX />);
};
If the only thing you'll ever do is just call doSomething and never use the helper instance again you can just do it with useEffect:
useEffect(() => {
new HelperClass().doSomething();
}, []);
If you do plan to use the helper instance at some later time then you could use the previous example with useMemo or useRef:
const helper = useRef();
useEffect(() => {
helper.current = new HelperClass();
//only called once after first render
helper.current.doSomething();
}, []);
//you still have the helper instance as helper.current
I'd go for useMemo
solution, but here's how you can do it with useRef
+ useEffect
to clear up some confusion:
const StatelessFunction = (props) => {
const helper = useRef(); // ref is equivalent of instance prop
useEffect(() => {
helper.current = new HelperClass();
helper.current.doSomething();
}, []); // this is equivalent of componentDidMount
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With