- public
- src
- index.js
- package.json
- README.md
- yarn.lock
src/index.js
import React from 'react'
import {render} from 'react-dom'
render(
<h1>app</h1>,
document.getElementById("root")
)
什么是Hooks
?
不通过编写类组件的情况下,可以在组件内部使用(
state
)和其他React
特性(生命周期
,content
)的技术
Hooks
为什么会出现
在之前的React
版本中,组件分为两种:函数式组件(或无状态组件(State less Function Component))和类组件,而函数式组件是一个比较的纯洁的props=>UI
的输入、输出关系,但类组件由于有组件自己的内部状态,所以其输出就由props
和state
决定,类组件的输入、输出关系就不再那么纯洁。同时也会带来下列问题:
- 1.状态逻辑难以服用。很多类组件都有一些类似的状态逻辑,但是为了重用这些状态逻辑,社区提出了
render props
或hoc
这些方案,但是这两种模式对组件的侵入性太强。另外,会产生组件嵌套地狱的问题 - 2.大多数开发者在编写组件时,不管这个组件有木有内部状态,会不会执行生命周期函数,都会将组件编写成类组件,后续迭代可能增加了内部状态,又增加了副作用处理,又在组件中调用了一些生命周期函数,文件代码行数日益增多,最后导致组件中充斥着无法管理的混乱的状态逻辑代码和各种副作用,各种状态逻辑散落在实例方法和生命周期方法中,维护性变差,拆分更是难上加难。
- 3.在类组件中,需要开发者额外去关注this问题,时间监听器的添加和移出等
State Hook
state hook
提供了一种可以在function component
中添加状态的方式。通过state hook
,可以抽取状态逻辑,使组件变得可测试,可重用。开发者可以在不改变组件层次结构的情况下,去重用状态逻辑。更好的实现关注点分离。
实现计数器
1.添加函数组件src/App.js
import React from 'react'
import {render} from 'react-dom'
const Counter=()=>{
return (
<div>
<button>-</button>
<span>10</span>
<button>+</button>
</div>
)
};
render(
<Counter/>,
document.getElementById("root")
)
2.引用useState
(src/App.js
)
import React,{useState} from 'react'
3.将useState
解构
const Counter=()=>{
const [count,setCount]=useState(0); //#insert 新增
return (
<div>
<button>-</button>
<span>10</span>
<button>+</button>
</div>
)
};
4.将解构出来的count
添加到jsx
中
const Counter=()=>{
const [count,setCount]=useState(0);
return (
<div>
<button>-</button>
<span>{count}</span> //#update 修改
<button>+</button>
</div>
)
};
5.给按钮添加点击事件,并设置count
值
const Counter=()=>{
const [count,setCount]=useState(0);
return (
<div>
<button onClick={()=>{setCount(count-1)}}>-</button> //#update 修改
<span>{count}</span>
<button onClick={()=>{setCount(count+1)}}>+</button> //#update 修改
</div>
)
};
6.useEffect组件更新 src/App.js
import React,{useState,useEffect} from 'react' //#update 修改
const Counter=()=>{
const [count,setCount]=useState(0);
// #insert 新增开始
/**
* useEffect的参数是一个回调,不管是组件挂载还是更新,都会触发这个回调函数 类似于componentDidMount和componentDidUpdate的结合
*/
useEffect(()=>{
document.title=`当前数值为:${count}`;
});
// #insert 新增结束
return (
<div>
<button onClick={()=>{setCount(count-1)}}>-</button>
<span>{count}</span>
<button onClick={()=>{setCount(count+1)}}>+</button>
</div>
)
};
几点说明:
- 1.
useState
推荐一种更加细粒度的控制状态的方式,即一个状态对应一个状态设置函数,其接受的参数将作为这个状态的初始值。其返回一个长度为2的元组,第一项为当前状态,第二项为更新函数。 - 2.
useState
的执行顺序在每一次更新渲染时必须保持一致,否则多个useState
调用将不会得到各自独立的状态,也会造成状态对应混乱。比如在条件判断中使用hook,在混选,嵌套函数中使用hook,都会造成hook执行顺序不一致问题。最后导致状态的混乱。另外,所有的状态声明都应该放在函数顶部,首先声明。 - 3.
useState
和setState
的区别
useState
将setState
进行覆盖式更新,而setState
则将状态进行合并式更新。
index.js源码
import React,{useState,useEffect} from 'react'
import {render} from 'react-dom'
const Counter=()=>{
const [count,setCount]=useState(0);
/**
* useEffect的参数是一个回调,不管是组件挂载还是更新,都会触发这个回调函数 类似于componentDidMount和componentDidUpdate的结合
*/
useEffect(()=>{
document.title=`当前数值为:${count}`;
});
return (
<div>
<button onClick={()=>{setCount(count-1)}}>-</button>
<span>{count}</span>
<button onClick={()=>{setCount(count+1)}}>+</button>
</div>
)
};
render(
<Counter/>,
document.getElementById("root")
)
网友评论