基础知识
React 中 setInterval 会重复生成。需要在return 中清除。
export default function App() {const [count, setCount] = useState(0)useEffect(() => {let timer = null;if(!timer){timer = setInterval(() => {setCount(count+1)},1000)}return () => {clearInterval(timer)}},[count])return (<div className="App"><h1>count value : {count}</h1></div>);}
Hooks相关
UseState
当 useState 触发更新时。连续更改相同的值。如果是原始值,组件不会重新 render。
如果是引用类型的值。组件会重复渲染。
import { useState } from "react";const UseState = () => {console.log("trigger count");const [count, setCount] = useState({ num: 1 });return (<><button onClick={() => setCount((e) => ({ ...e, num: e.num + 1 }))}>increasement -{count.num}</button><button onClick={() => setCount({ num: 0 })}>increasement -{0}</button></>);};export default UseState;
React.memo
在react 中,当父组件渲染时,有可能造成子组件不必要的渲染,为了优化这种行为,我们可以使用React.memo 来包裹子组件,确保只有 props 发生变化时才会重新渲染。
使用误区
在 React 中,如果子组件的有 children 属性的话。有两种情况第一种是你的children是一个文本节点,这时能正常工作。第二种是除了文本节点的HTML 元素,这时使用 React.memo 包裹是无效的。原因是这种情况下props.children是一个引用,所以会导致子组件总是重渲染。
useMemo
useMemo 是一个返回的是一个值。跟useCallback 类似。第一个参数是需要“缓存”的值,第二个参数是该组件重新渲染时的依赖值,如果依赖值发生变化,组件就重新渲染。
useCallback
useCallback返回一个函数,同样需要一个依赖值来决定函数是否渲染。常用的场景就是组件 执行了方法,那么依赖值发生变化,该方法/函数就会重新渲染。调用此方法的组件也会重新渲染。
useCallback通常跟React.memo一起使用,原因是组件传入的props 包括方法和值,值包括原始值和引用值。React.memo 只能保证 props 中全部是原始值时,组件不会重新渲染。如果是引用值,那么需要借助 useMemo 缓存复杂的引用值。props 包含执行的方法时。则需要使用 useCallback 来缓存方法。通过这三个api,才能精确的控制的组件的渲染。起到优化的作用。
import "./styles.css";import PersonInfo from "./PersonInfo";import { useCallback, useState } from "react";export default function App() {const [age, setAge] = useState(18);const [name, setName] = useState("qujun");const handleChangeAge = useCallback(() => {setAge(age + 1)},[age])const changeName = useCallback(() => {const index = Math.floor(Math.random()*(-3) + 3);const val = ['中','国','你','好'].splice(index,1)setName(val[0])},[name])return (<div className="App"><h1>Hello CodeSandbox</h1><PersonInfo handleClick={handleChangeAge} name={age}>changeAge</PersonInfo><PersonInfo handleClick={changeName} name={name} >changeName</PersonInfo></div>);}
