I am trying understand what the difference is between:
React.useEffect(() => {
let timerId = Js.Global.setInterval(() => tick(), 1000);
Some(() => Js.Global.clearInterval(timerId));
});
React.useEffect0(() => {
let timerId = Js.Global.setInterval(() => tick(), 1000);
Some(() => Js.Global.clearInterval(timerId));
});
They both have the same type signature and both compile but the useEffect0
does nothing:
// useEffect0 : unit => option(unit => unit) => unit
// useEffect : unit => option(unit => unit) => unit
To use the example at https://reasonml.github.io/reason-react/blog/2019/04/10/react-hooks, it uses useEffect
but if you change so that it uses useState
instead of useReducer
you have to change useEffect
to useEffect0
Original version using useEffect0
:
type action =
| Tick;
type state = {
count: int,
};
[@react.component]
let make = () => {
let (state, dispatch) = React.useReducer(
(state, action) =>
switch (action) {
| Tick => {count: state.count + 1}
},
{count: 0}
);
React.useEffect0(() => {
let timerId = Js.Global.setInterval(() => dispatch(Tick), 1000);
Some(() => Js.Global.clearInterval(timerId))
});
<div>{ReasonReact.string(string_of_int(state.count))}</div>;
};
After removing useReducer
and using useEffect
:
[@react.component]
let make = () => {
let (state, dispatch) = React.useState(()=>
{count: 0}
);
let tick =()=> dispatch(_=>{count: state.count + 1});
React.useEffect(() => {
let timerId = Js.Global.setInterval(() => tick(), 1000);
Some(() => Js.Global.clearInterval(timerId))
});
<div>{ReasonReact.string(string_of_int(state.count))}</div>;
};
So why does the call change when using the different structure?
Any links or explanation would be greatly appreciated.
Thank you.
React.useEffect(f)
in Reason compiles to React.useEffect(f)
in JavaScript. React.useEffect0(f)
in Reason compiles to React.useEffect(f, [])
in JavaScript.
The difference is that second []
argument that's inserted in the JavaScript. By default, useEffect
in JavaScript fires with every render. By adding the empty array in the second argument, we're telling React to only fire it once, when the component first renders.