react hooks in practice

useState

和 react 的 this.state 是一个东西

useEffect

在 component.DidMount 和 componnet.DidUpdate 这两个生命周期内执行。如果在useEffect中有return的话,return部分在componnetWillUnmount阶段调用。

关于 useEffect 第二个参数的三种情况:
codesandbox

  1. 不写。视情况而定,会发生语法报错,说:缺失依赖值,可能会导致对依赖的无限查找。不写就是默认对你所有用到的值变化的时候执行。
  2. 空数组[]。当useEffect 中用到了依赖值,却设置了空依赖列表,会发生报错,强制忽略报错,可以用来阻止代码执行。
  3. 正常情况下的所用值形成的依赖列表。

useEffect 的应用:

  1. 有些在浏览器中才能使用的,而在build阶段不可以使用的,比如 localstorage, react router中的location.state.xxx,这部分的代码可以写为 useEffect(...some code...,[])
  2. 结合 useRef 写一个自定义hook储存 previous state。(下文中的demo还显示了 useRef 和 组件外部变量的应用区别。)
    codesandbox
  3. 设置定时器,对input输入内容的防抖。
    oi-wiki-search.js
    codesandbox

useContext

当一个较深层次的子组件要使用父组件的一些值的时候,使用useContext可以避免props层层传递的累赘,而直接在context.provider包裹下的组件中,使用context.consumer或者useContext获取顶层父组件的值(provider value),而不单单是上一层父组件的值。

可以应用在主题和语言设置上。
intl context provider部分
intl context consumer部分
intl useContext 部分

或许可以考虑写一个单独demo出来??

useCallback 、 useMemo and React.Memo

这三者都有很大的相似性。react 在对props进行相等性检查时,对于相同值但是代码来源不同的数组和对象的对比结果会为false,这就导致很多不必要的重计算和重渲染,这三个API都可以用来处理这个问题。

1
2
3
4
5
6
7
//相等性检查
const n1 = 1
const n2 = 1
n1 === n2 // true
const a1 = [1]
const a2 = [1]
a1 === a2 // false

在下面这个demo可以看到,options的值没有变化,可是由于js的工作机制,在上层组件(在demo中上层组件是App)发生更新时,每次传入 Apple 组件的参数,都被认为是新的,useEffect的回调函数进行了re-run,(re-render了吗?可由devtools监测到HTML元素),并且在codesandbox也可以看到(react-hooks/exhaustive-deps)eslint给出的使用useMemo的修改建议。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import React,{useEffect, useState} from "react";
import "./styles.css";

const Apple = ({time,count}) => {
const options = {time,count}
useEffect(()=>{
console.log(`thers is ${options} apples`)
},[options])
return(
<div>apple</div>
)
}
export default function App() {
const [girl,setGirl] = useState(0)
const [count,setCount] = useState(0)
const [time,setTime] = useState(0)
return (
<div className="App">
<h1 onClick={() => setGirl(girl+1)}>{girl}</h1>
<h2>Start editing to see some magic happen!</h2>
<Apple count={count} time = {time} />
</div>
);
}

但是参看博客,任何性能优化都具有代价,在进行使用前都应该测量一下,性能优化的代价是不是足以抵销重计算的时间。

useRef

useRef 会在每次渲染时返回同一个 ref 对象,并且变更 .current 属性的变化不会引发组件重新渲染。

官方文档的应用示例:阻止input框不必要的rerender

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function App() {
const [value, setValue] = React.useState("");
const valueRef = React.useRef();

const handleClick = e => {
setValue(valueRef.current.value);
};

return (
<div className="App">
<h4>Value: {value}</h4>
<input ref={valueRef} />
<Button onClick={handleClick}>Button</Button>
</div>
);
}
0%