当前位置:主页 > >

三分钟搞懂react-hooks及实例代码

时间:2023-03-05 12:22:18 | 栏目: | 点击:

背景

介绍Hooks之前,首先要说一下React的组件创建方式,一种是类组件,一种是纯函数组件,并且React团队希望,组件不要变成复杂的容器,最好只是数据流的管道。开发者根据需要,组合管道即可。也就是说组件的最佳写法应该是函数,而不是类。
但是我们知道,在以往开发中类组件和纯函数组件的区别是很大的,纯函数组件有着类组件不具备的多种特点:

纯函数组件没有状态
纯函数组件没有生命周期
纯函数组件没有this

这就注定,我们所推崇的函数组件,只能做UI展示的功能,涉及到状态的管理与切换,我们不得不用类组件或者redux,但我们知道类组件的也是有缺点的,比如,遇到简单的页面,代码会显得很重,并且每创建一个类组件,都要去继承一个React实例;至于Redux,更不用多说,很久之前Redux的作者就说过,“能用React解决的问题就不用Redux”。

useState

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} times</p>
            <button onClick={()=>{setCount(count+1)}}>Click me</button>
        </div>
    )
}
export default App2;

多状态声明

使用多条语句声明不同的状态

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

useEffect():副作用钩子。可以用来更好的处理副作用,如异步请求等,Hooks的useEffect()也是为函数组件提供了处理副作用的钩子。在类组件中我们会把请求放在componentDidMount里面,在函数组件中我们可以使用useEffect()。

useEffect相当于componentDidMount和componentDidUpdate。
缺点:由于它是异步的因此不能实时处理。

类组件中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;

useEffect模拟类组件中componentDidMount和componentDidUpdate

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;

useEffect实现componmentWillUnment

先写两个路由跳转页面,并配置路由

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} 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;

父子组件传值useContext

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

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

您可能感兴趣的文章:

相关文章