介绍Hooks之前,首先要说一下React的组件创建方式,一种是类组件
,一种是纯函数组件
,并且React团队希望,组件不要变成复杂的容器,最好只是数据流的管道。开发者根据需要,组合管道即可。也就是说组件的最佳写法应该是函数
,而不是类。
但是我们知道,在以往开发中类组件和纯函数组件的区别是很大的,纯函数组件有着类组件不具备的多种特点:
纯函数组件没有状态
纯函数组件没有生命周期
纯函数组件没有this
这就注定,我们所推崇的函数组件,只能做UI展示的功能,涉及到状态的管理与切换,我们不得不用类组件或者redux,但我们知道类组件的也是有缺点的,比如,遇到简单的页面,代码会显得很重,并且每创建一个类组件,都要去继承一个React实例;至于Redux,更不用多说,很久之前Redux的作者就说过,“能用React解决的问题就不用Redux”。
useState():状态钩子。纯函数组件没有状态,useState()用于为函数组件引入状态。
点击加一效果,分别用类组件和函数组件实现。可以看出用hooks写出的代码更加精简。
const [count,setCount] = useState(0)
;//数组解构,相当于下面三句话
let _useState = useState(0);
let count = _useState[0];
let setState = _useState[1]
import React,{Component} from "react";
class App1 extends Component{
constructor(props) {
super(props);
this.state={
count:0
}
}
addCount(){
this.setState({count:this.state.count+1})
}
render() {
return(
<div>
<p>you clicked {this.state.count} times</p>
<button onClick={this.addCount.bind(this)}>Click me</button>
</div>
)
}
}
export default App1;
使用sueState重写上面计数组件。
import React,{useState} from "react";
function App2(){
const [count,setCount] = useState(0);//数组解构
return(
<div>
<p>You cliked {count} timesp>
使用多条语句声明不同的状态
import React,{useState} from "react";
function App3(){
const [name,setName] = useState('刘备');//数组解构
const [age,setAge] = useState(25);
const [sex,setSex] = useState('男')
return(
<div>
<p>姓名:{name}</p>
<p>年龄:{age}</p>
<p>性别:{sex}</p>
</div>
)
}
export default App3;
useEffect():副作用钩子。可以用来更好的处理副作用,如异步请求等,Hooks的useEffect()也是为函数组件提供了处理副作用的钩子。在类组件中我们会把请求放在componentDidMount里面,在函数组件中我们可以使用useEffect()。
useEffect相当于componentDidMount和componentDidUpdate。
缺点:由于它是异步的因此不能实时处理。
import React,{Component} from "react";
class App4 extends Component{
constructor(props) {
super(props);
this.state={
count:0
}
}
componentDidMount() {
console.log(`componentDidMount=>you clicked ${this.state.count}`)
}
componentDidUpdate() {
console.log(`componentDidUpdate=>you clicked ${this.state.count}`)
}
addCount(){
this.setState({count:this.state.count+1})
}
render() {
return(
<div>
<p>you clicked {this.state.count} times</p>
<button onClick={this.addCount.bind(this)}>Click me</button>
</div>
)
}
}
export default App4;
import React,{useState,useEffect} from "react";
function App5(){
const [count,setCount] = useState(0);//数组解构
useEffect(()=>{
console.log(`useEffect=>you clicked ${count} times`)
})
return(
<div>
<p>You cliked {count} times</p>
<button onClick={()=>{setCount(count+1)}}>Click me</button>
</div>
)
}
export default App5;
先写两个路由跳转页面,并配置路由
import React,{useState,useEffect} from "react";
import { BrowserRouter as Router, Route, Link, Routes } from 'react-router-dom'
function Index(){
return <h2>Index页面</h2>
}
function List(){
return <h2>List页面</h2>
}
function App5(){
const [count,setCount] = useState(0);//数组解构
return(
<div>
<div>
<p>You cliked {count} times</p>
<button onClick={()=>{setCount(count+1)}}>Click me</button>
</div>
<Router>
<div>
<ul>
<li><Link to="/">首页</Link></li>
<li><Link to="/list/">list</Link></li>
</ul>
<Routes>
<Route path="/" exact element={<Index/>}/>
<Route path="/list/" element={<List/>}/>
</Routes>
</div>
</Router>
</div>
)
}
export default App5;
使用useEffect表示进入页面的状态。
解绑时使用return,这时发现我们点击按钮时也会发生改变,这是因为只要组件发生改变,它就会触发解绑。解决方法使用第二个参数。
import React,{useState,useEffect} from "react";
import { BrowserRouter as Router, Route, Link, Routes } from 'react-router-dom'
function Index(){
useEffect(()=>{
console.log(`useEffect=>Index页面`)
return ()=>{
console.log('跳转页面')
}
})
return <h2>Index页面</h2>
}
function List(){
useEffect(()=>{
console.log(`useEffect=>List页面`)
})
return <h2>List页面</h2>
}
function App5(){
const [count,setCount] = useState(0);//数组解构
return(
<div>
<div>
<p>You cliked {count} times</p>
<button onClick={()=>{setCount(count+1)}}>Click me</button>
</div>
<Router>
<div>
<ul>
<li><Link to="/">首页</Link></li>
<li><Link to="/list/">list</Link></li>
</ul>
<Routes>
<Route path="/" exact element={<Index/>}/>
<Route path="/list/" element={<List/>}/>
</Routes>
</div>
</Router>
</div>
)
}
export default App5;
解绑限制,第二个参数是一个数组,如果数组为空表示页面被销毁触发,如果有变量,表示只有这个变量状态变化才会触发。
import React,{useState,useEffect} from "react";
import { BrowserRouter as Router, Route, Link, Routes } from 'react-router-dom'
function Index(){
useEffect(()=>{
console.log(`useEffect=>Index页面`)
return ()=>{
console.log('跳转页面')
}
},[])
return <h2>Index页面h2>
}
function List(){
useEffect(()=>{
console.log(`useEffect=>List页面`)
})
return <h2>List页面h2>
}
function App5(){
const [count,setCount] = useState(0);//数组解构
return(
<div>
<div>
<p>You cliked {count} timesp>
useContext():共享状态钩子。作用就是可以做状态的分发,在React16.X以后支持,避免了react逐层通过Props传递数据。
使用步骤
1、先使用createContext创建上下文
2、然后使用Provider将值给提供出去
3、接收时用useContext接收就可以了
import React,{useState,createContext,useContext} from "react";
const CountContext = createContext();
function Counter(){
let count = useContext(CountContext);
return (<h2>{count}</h2>)
}
function App6(){
const [count,setCount] = useState(0);//数组解构
return(
<div>
<p>You cliked {count} times</p>
<button onClick={()=>{setCount(count+1)}}>Click me</button>
<CountContext.Provider value={count}>
<Counter/>
</CountContext.Provider>
</div>
)
}
export default App6;
useReducer():Action钩子
。在使用React的过程中,如遇到状态管理,一般会用到Redux,而React本身是不提供状态管理的。而useReducer()提供了状态管理。首先,关于redux我们都知道,其原理是通过用户在页面中发起action,从而通过reducer方法来改变state,从而实现页面和状态的通信。而Reducer的形式是(state, action) => newstate
。
import React,{useReducer} from "react";
function Reduser(){
const [count,dispath] = useReducer((state,action)=>{
switch (action){
case "add":
return state+1
case "sub":
return state-1
default:
return state
}
},0)
return(
<div>
<h2>现在的分数是{count}</h2>
<button onClick={()=>{dispath('add')}}>add</button>
<button onClick={()=>{dispath('sub')}}>sub</button>
</div>
)
}
export default Reduser