Reputation: 265
Im writing my product in React Hooks and yes, Im just new to it.
Today I have math about useCallback performance.This makes me consider a lot to use useCallback or not use.
Let have a look. As we know, useCallback is use for better performance.
function MainScreen() {
const [email, setEmail] = useState("");
const [pwd, setPwd] = useState(""):
const onAuthenticate = useCallback(() => {
MyApi.authenticate(email, pwd);
}, [email, pwd]);
return <div>
<MyCustomButton onPress={onAuthenticate}>LOGIN</MyCustomButton>
</div>;
}
In the example above, let's assume there are two inputs of email and password then MyCustomButton
will be rendered all the times email or password changes. I tried to use useCallback
to reduce number times of render but for me, it is not good enough.
Later, I figured out a way, take out email and pwd in dependencies and use useRef
to hold value of email and password.
function MainScreen() {
const [email, setEmail] = useState("");
const [pwd, setPwd] = useState(""):
const emailRef = useRef(email);
const pwdRef = useRef(pwd);
const onAuthenticate = useCallback(() => {
MyApi.authenticate(emailRef.current, pwdRef.current);
}, []);
useEffect(() => {
emailRef.current = email;
pwdRef.current = pwd;
}, [email, pwd]);
return <div>
<MyCustomButton onPress={onAuthenticate}>LOGIN</MyCustomButton>
</div>;
}
With this approach, it stops rendering in MyCustomButton
every time email or password changes.
Is it actually better in performance and cost? What do you think guys?
Thanks for sharing.
Upvotes: 1
Views: 2309
Reputation: 2351
in this case, I would like use React.memo instead of useCallback. use React.memo to make sure this component will not call render cased by parent, once component call render, email or pwd have changed, so useCallback is unnecessary
function MainScreen() {
const [email, setEmail] = useState("");
const [pwd, setPwd] = useState(""):
const onAuthenticate = () => {
MyApi.authenticate(email, pwd);
};
return <div>
<MyCustomButton onPress={onAuthenticate}>LOGIN</MyCustomButton>
</div>;
}
export default React.memo(MainScreen)
Upvotes: 0
Reputation: 168
Since you are only performing an API call, I recommend not to use useCallback()
. Make it a normal function instead.
You could be doing a premature optimization. You should only do performance optimization, if you are performing heavy computations on your app and you need to memoize your values.
An in-depth comparison of a normal function vs a function that uses useCallback()
can be seen from here.
Upvotes: 0
Reputation: 1963
The issue that I am seeing with your code is not with useCallback
- it's with useState
.
A rule of thumb in react (whether you use hooks or not) is that the state has a direct impact on what is being displayed. If you modify the state, it means that the component should be re-rendered.
This rationale is what makes your component re-render when using useState. React assumes that email
and password
are things that change how your component should look like, therefore, it is being rerendered whenever you change one of their values.
If you don't actually use email
and pwd
in MyCustomButton
, then using useRef
instead of useState
makes more sense.
However, the way you are using it in your second code sample doesn't make a lot of sense: You are combining useState
and useRef
so that when email
changes (which will be the case when you use setEmail
, then you update the ref with the same value. The only benefit that you get out of it is that onAuthenticate is not reconstructed every time.
It would be more beneficial to skip useState
entirely, but from the code you posted, it is difficult to actually propose a different solution, as it is not clear how/when email
and pwd
are actually set.
Upvotes: 1