如果自学可看这几个链接:
中文解析:这里
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
它旗下有这么几个 API:

搞懂了这 10 个 API,算是彻底了解了 Hooks API 了
关于这篇 文章:

初学者需要教学者通过一些代码比较智障的方法来教会他们……
yarn info react versions
有一些新特性,你需要安装alpha版本才能用:

把package.json里边的dependencies字段旗下的react和react-dom改成这个alpha版的,重新yarn add一下就好了!
用 codesandbox 会更简单!改一下值,就能自动更新库的版本了!
之前说到,函数组件是咩有状态的,如果你要想有状态的话,那就得用class组件,不过,之后出了这个 Hooks API,意味着函数也是有状态的!
没有 Hooks API 之前,你想这样写:

有了 Hooks API 之后:
function App() {
// count 的初始值为 0,setCount 表示更新 count 的函数
// 返回一个数组
const [count, setCount] = useState(0);
const add = (n) => {
setCount(count+n)
}
return (
<div>
<div>{count}</div>
<div>
<button onClick={() => { add(1); }} > +1 </button>
</div>
</div>
);
}
可以看到自从有了useState之后,我们就不需要用class来维护一个组件的状态了! -> 直接就是通过useState,然后给一个初始的0,然后再通过count拿到最新的值,如果要更新count那就调用setCount
💡:两次引入react,也是只有一次加载?

用了useState之后,代码变得更简洁了,那我们之前用class是怎么写的呢?
class App1 extends Component {
constructor() {
super();
this.state = {
count: 0,
};
}
add(n) {
this.setState({
count: this.state.count + n,
});
}
minus(n) {
this.setState({
count: this.state.count - n,
});
}
render() {
return (
<div>
<div>{this.state.count}</div>
<div>
<button onClick={() => { this.add(1); }} > {" "} +1{" "} </button>
<button onClick={() => { this.minus(1); }} > {" "} -1{" "} </button>
</div>
</div>
);
}
}
可以看到,我们需要写这些废话:
extends Componentconstructorsuperthisrender而我们用了 Hooks API 的函数组件,就没有废话了……每一行代码都没有多余的……
class组件了,只要你把 React 升级到 16.8useState之后,那就意味着你可以很简单的进行函数的赋值和更新了function App() {
// count 的初始值为 0,setCount 表示更新 count 的函数
const [count, setCount] = useState(0);
const [user,setUser]= useState({name:'frank',age:18})
const add = (n) => {
setCount(count + n);
};
const minus = (n) => {
setCount(count - 1);
};
const old = (n) => {
setUser({
...user,
age: user.age +1
})
}
return (
<div>
<div>{count}</div>
<div>
<button onClick={() => { add(1); }} > {" "} +1{" "} </button>
<button onClick={() => { minus(1); }} > {" "} -1{" "} </button>
</div>
<div>{user.name},{user.age}</div>
<button onClick={()=>{old(1)}}>age + 1</button>
</div>
);
}
如果你想更新复杂的state,那么其它不更新的属性直接拷贝,更新的则赋值……
💡:setX这样就是在给一个x赋值,但是我很好奇的是,x就是const声明的变量啊!为啥还可以重新赋值呢?
在setUser的时候,不能单独对某个属性该值,你得把原属性搞过来后再改值……
重新呈现组件后,将再次执行该函数,从而创建新的作用域,创建新的
user变量,该变量与先前的变量无关。
➹:为什么 useState 可以使用 const 解构赋值? - 知乎
需求:
function App() {
// count 的初始值为 0,setCount 表示更新 count 的函数
const [count, setCount] = useState(0);
let [user,setUser]= useState({name:'frank',age:18,hobbies:['打 lol','敲 code','看篮球']})
const add = (n) => {
setCount(count + n);
};
const minus = (n) => {
setCount(count - 1);
};
const old = (n) => {
setUser({
...user,
age: user.age +1
})
}
const delHobby = () => {
// 这种写法很不直观……
// 删除第二项……
user.hobbies.splice(1,1)
setUser({
...user
})
}
const addHobby = () => {
// 姿势 1
// user.hobbies.push(Math.random())
// setUser({
// ...user
// })
// 姿势 2
let newHobby = Math.random()
setUser({
...user,
hobbies:[...user.hobbies,newHobby]
})
}
return (
<div>
<div>{count}</div>
<div>
<button onClick={() => { add(1); }} > {" "} +1{" "} </button>
<button onClick={() => { minus(1); }} > {" "} -1{" "} </button>
</div>
<div>{user.name},{user.age}</div>
<button onClick={()=>{old(1)}}>age + 1</button>
<div>{user.hobbies.join(',')}</div>
<button onClick={()=>{delHobby()}}>删除一个爱好</button>
<button onClick={()=>{addHobby()}}>添加一个爱好</button>
</div>
);
}
不管是简单的0,还是复杂的数组,都可以用useState来改变函数的状态! -> 功能都可以实现,只是就得写一些复杂的 JS 代码罢了!
总之,函数组件不仅可以有一个state,还可以有多个state,而且每个state也可以有复杂的结构!
💡:能否把useState代码写到App函数的外边去呢?
CRM 套路,一旦 copy 的代码,运行成功,我们就在这个代码的基础上各种改!

代码编译结果:
src\demo\Add.js
Line 4:27: React Hook "useState" cannot be called at the top level. React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooks
Search for the keywords to learn more about each error.
这就是第一个文档里边没有告诉我们的知识:你不能把useState拿到函数外边去 -> 没有为什么,React 就是不准!
这个问题告诉我们「并不需要一直死磕文档,有时候只需要稍微改一下例子,就能发现一些我们不能这样做的知识点了」
💡:状态名以及修改状态的函数名能否随意起名?
把
const [count, setCount] = useState(0);
改成这样的:
const [x, y] = useState(0);
也是可以的,只要搞清楚顺序就好了 -> 第一个是状态,第二个是改状态的赋值函数
总之,这与名字无关!
方方学习套路:把可以改的都改一下,看看有什么效果,然后再把效果记录下来!
文档:使用 Effect Hook – React、使用 Effect Hook – React 中文文档 v16.6.3
要了解Effect Hook,必须先了解「副作用」

这就像是高中英语听力一样 -> 重要的那个单词老是听不懂……
用通俗的话来讲什么是副作用(可能不对,但至少能听懂):
如果你在看一个函数,发现它的函数体里边有代码不知道是哪儿来的,那么这个函数就是有副作用的函数!因为它依赖了不知道从哪儿来的东西!

生活例子:
总之,就是一些让你感到惊讶的东西出现在了不该出现的地方……
副作用就是依赖了一些乱七八糟的函数!当然,这其实并没有什么坏处!
如果你的这个函数是个有副作用的函数,那么你就把这个函数写到useEffect里边
例子:把状态交给与div#root同级的div#output

我挺想知道 Hook API 的执行时机是怎样的,在上边这个例子里边,我更新了
count的值,div#output的内容就会自动改变……难道每次更新状态,Effect这个函数都会重新执行一遍吗?
小结:
useEffect里边可以引入最新的count的值Hooks API
请使用 Hooks API 做出一个 couter 应用:
function Test() {
const [n, setN] = useState(0);
const add1 = () => {
setN(n + 1);
};
return (
<div>
<div>{n}</div>
<button
onClick={() => {
add1();
}}
>
+1
</button>
</div>
);
}