先看大纲 我感觉我不会学完 但是 我会学我觉得好用的 后续用到在持续更新
-
基本的钩子
- useState
- useEffect
- useContext
-
添加的钩子
- useReducer
- useCallback
- useMemo
- useRef
- useImperativeMethods
- useMutationEffect
- useLayoutEffect
react Hook 是react 新推出的功能 目的很简单下面几个问题来回答你的疑惑
你还在为该使用无状态组件(Function)还是有状态组件(Class)而烦恼吗?
——拥有了hooks,你再也不需要写Class了,你的所有组件都将是Function。
你还在为搞不清使用哪个生命周期钩子函数而日夜难眠吗?
——拥有了Hooks,生命周期钩子函数可以先丢一边了。
你在还在为组件中的this指向而晕头转向吗?
——既然Class都丢掉了,哪里还有this?你的人生第一次不再需要面对this。
useState
例子 正常版本 class 创建组件 定义state 用setState 来改变组件样式
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
如果是无状态组件 则
const Example =()=>{<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
}
有了hook 在不用class 和function 去分 都可以写成 function function 也能有储存变量进行行为的能力
import { useState } from 'react';
function Example() {
const [count, setCount] = useState(0);
// 第一个参数类似于state 第二个是函数 类似于 setState
//count 相当于this.state.count useState(0)相当于this.setState({conut:0})
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
useEffect
你可以把 useEffect Hooks 视作 componentDidMount、componentDidUpdate 和 componentWillUnmount 的结合
我们在 React 更新 DOM 之后立刻更新 document title
我觉得的用途主要是在update 的时候判断某个值做某种操作用的 类似于替代之前的钩子函数
老样子 正常版本 class
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
componentDidMount() {
document.title = `You clicked ${this.state.count} times`;
}
componentDidUpdate() {
document.title = `You clicked ${this.state.count} times`;
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
useEffect 版本
import { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
//默认情况下 它会在第一次 render 和之后的每次 update 后运行
useEffect(() => {
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
聊聊 他的忌讳
Hooks的规则
钩子是JavaScript函数,但它们强加了两个额外的规则:
- 只能在顶层调用Hooks。不要在循环,条件或嵌套函数中调用Hook
- 仅从React功能组件调用Hooks。 不要从常规JavaScript函数中调用Hook。 (还有另一个有效的地方叫Hooks - 你自己的定制Hooks。我们马上就会了解它们。)
为什么只能顶层 不要循环或者嵌套呢?
https://reactjs.org/docs/hooks-rules.html#explanation
我们看个官网的例子
useState('Mary') // 1. Initialize the name state variable with 'Mary'
useEffect(persistForm) // 2. Add an effect for persisting the form
useState('Poppins') // 3. Initialize the surname state variable with 'Poppins'
useEffect(updateTitle) // 4. Add an effect for updating the title
// -------------
// Second render
// -------------
useState('Mary') // 1. Read the name state va
useEffect(updateTitle) // 4. Replace the effect for updating the titleriable (argument is ignored)
useEffect(persistForm) // 2. Replace the effect for persisting the form
useState('Poppins') // 3. Read the surname state variable (argument is ignored)
如果我们判断写
// ? We're breaking the first rule by using a Hook in a condition if (name !== '') { useEffect(function persistForm() { localStorage.setItem('formData', name); }); }
该name !== ''条件是true在第一渲染,所以我们运行此挂钩。但是,在下一次渲染时,用户可能会清除表单,从而形成条件false。现在我们在渲染过程中跳过此Hook,Hook调用的顺序变得不同:
useState('Mary') // 1. Read the name state variable (argument is ignored)
// useEffect(persistForm) // ? This Hook was skipped!
useState('Poppins') // ? 2 (but was 3). Fail to read the surname state variable
useEffect(updateTitle) // ? 3 (but was 4). Fail to replace the effect
React不会知道第二个useStateHook调用返回什么。React期望此组件中的第二个Hook调用对应于persistForm效果,就像在前一个渲染期间一样,但它不再存在。从那时起,在我们跳过的那个之后的每个下一个Hook调用也会移动一个,导致错误。
这就是必须在我们组件的顶层调用Hooks的原因。如果我们想要有条件地运行一个效果,我们可以把这个条件放在我们的Hook中:
useEffect(function persistForm() {
// ? We're not breaking the first rule anymore
if (name !== '') {
localStorage.setItem('formData', name);
}
});
如果要在 useEffect 中 修改useState属性 可能造成死循环 因为每次‘state‘ 改变 userEffect 都会执行 所以你需要做如下操作
const [xAxis,setXAxis] =useState([])
const [num]=useState(Math.random())
const [yAxis,setYAxis] =useState([])
useEffect(()=>{
getVarietyChart().then((val)=>{
setXAxis(val.xAxis)
setYAxis(val.yAxis)
})
},[]) //后面加入[] ,内是条件,比如 我写num 那么在每次num改变时才会执行,如果写[ ] 那只会在 初始化的时候执行一次
,补充一点 useEffect 中 初始化一定会执行一次 所以不能把它当做普通函数来用哦
如果你想写函数大可
const [xAxis,setXAxis] =useState([])
const [num]=useState(Math.random())
const [yAxis,setYAxis] =useState([])
function test(){
}
useEffect(()=>{
getVarietyChart().then((val)=>{
setXAxis(val.xAxis)
setYAxis(val.yAxis)
})
},[])
这样直接写即可