我正在用React Hooks编写我的产品,是的,我刚刚接触它。
今天我对useCallback的性能进行了数学计算。这使我考虑了很多使用useCallback或不使用的情况。
看看。众所周知,useCallback可以提高性能。
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>;
}
在上面的示例中,假设有两个电子邮件和密码输入,然后MyCustomButton
将在电子邮件或密码更改的所有时间呈现。我尝试使用useCallback
来减少渲染次数,但对我而言,这还不够好。
后来,我想出了一种方法,取出依赖项中的电子邮件和密码,并使用useRef
来保存电子邮件和密码的值。
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>;
}
采用这种方法,每次更改电子邮件或密码时,它都会停止在MyCustomButton
中呈现。
实际上在性能和成本上更好吗?你们觉得呢?
感谢分享。
答案 0 :(得分:0)
我在您的代码中看到的问题与useCallback
无关,而与useState
无关。
反应(无论是否使用挂钩)的经验法则是,状态对显示的内容有直接影响。如果您修改状态,则意味着应重新渲染组件。
此基本原理是使您在使用useState时重新呈现组件的原因。 React假设email
和password
会改变组件的外观,因此,只要您更改其值之一,它就会被重新渲染。
如果您实际上并未在email
中使用pwd
和MyCustomButton
,那么使用useRef
而不是useState
更有意义。
但是,在第二个代码示例中使用它的方式没有多大意义:您将useState
和useRef
组合在一起,以便email
发生变化时(使用setEmail
时会出现这种情况,然后使用相同的值更新ref。唯一的好处是不会每次都重新构造onAuthenticate。
完全跳过useState
会更有利,但是从您发布的代码中,实际上很难提出不同的解决方案,因为尚不清楚email
和{{ 1}}实际已设置。
答案 1 :(得分:0)
由于您仅执行API调用,因此建议不使用 useCallback()
。使其改为正常功能。
您可能正在进行过早的优化。仅当您在应用上执行大量计算并且需要记住您的值时,才应该进行性能优化。
从here.可以看到普通函数与使用useCallback()
的函数的深入比较。
答案 2 :(得分:0)
在这种情况下,我想使用React.memo而不是useCallback。 使用React.memo来确保该组件不会调用父对象设置的渲染, 一旦组件调用的呈现方式,电子邮件或密码更改了,那么useCallback就不再需要
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)