Hook基础

React Hooks就是用函数的形式代替原来的继承类的形式,并且使用预函数的形式管理state,有Hooks可以不再使用类的形式定义组件了。这时候你的认知也要发生变化了,原来把组件分为有状态组件和无状态组件,有状态组件用类的形式声明,无状态组件用函数的形式声明。那现在所有的组件都可以用函数来声明了。

用了它简直不要太爽,可以说是改变了编程的方式。

下面对比下就知道多爽:

class的方式:

import React, { Component } from 'react';

class Example extends Component {
    constructor(props) {
        super(props);
        this.state = { count:0 }
    }
    render() { 
        return (
            <div>
                <p>You clicked {this.state.count} times</p>
                <button onClick={this.addCount.bind(this)}>Chlick me</button>
            </div>
        );
    }
    addCount(){
        this.setState({count:this.state.count+1})
    }
}

export default Example;

hook写法:

import React, { useState } from 'react';
function Example(){
    const [ count , setCount ] = useState(0);
    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={()=>{setCount(count+1)}}>click me</button>
        </div>
    )
}
export default Example;

直观上代码变少了,而且易理解,符合我们函数式编程的思想。

hooks的目的就是让你不再写class,让function一统江湖。

 const [ count , setCount ] = useState(0);

分析下,es6语法里用数组结构来定义变量和一个设置变量的方法,后面的useState相当于给变量附一个初值。

<button onClick={()=>{setCount(count+1)}}>click me</button>

利用setCount方法直接写一个箭头函数,且react自带记忆功能,能帮我们记忆上一次的状态值。

那变量多个的时候,usestate怎么自己找到变量赋初值呢?其实也不难,就是按顺序一个一个赋值。且useState不能放在条件语句里,必须按相同的顺序来渲染。

用useEffect代替常用的生命周期函数,再来个对比吧,看看多方便:

这次先来看hook方式:

import React, { useState , useEffect } from 'react';
function Example(){
    const [ count , setCount ] = useState(0);
    //---关键代码---------start-------
    useEffect(()=>{
        console.log(`useEffect=>You clicked ${count} times`)
    })
    //---关键代码---------end-------

    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={()=>{setCount(count+1)}}>click me</button>
        </div>
    )
}
export default Example;

再看看原来class的方式:
import React, { Component } from ‘react’;

class Example3 extends Component {
constructor(props) {
super(props);
this.state = { count:0 }
}

componentDidMount(){
    console.log(`ComponentDidMount=>You clicked ${this.state.count} times`)
}
componentDidUpdate(){
    console.log(`componentDidUpdate=>You clicked ${this.state.count} times`)
}

render() { 
    return (
        <div>
            <p>You clicked {this.state.count} times</p>
            <button onClick={this.addCount.bind(this)}>Chlick me</button>
        </div>
    );
}
addCount(){
    this.setState({count:this.state.count+1})
}

}

export default Example3;

效果一样,这是为何?因为useEffect在组件第一次渲染和以后的每次更新都会运行,即包含上面两个生命周期函数的功能,用return方式可实现componentwillunmount(组件解绑)。像这样:

function Index() {
    useEffect(()=>{
        console.log('useEffect=>老弟你来了!Index页面')
        return ()=>{
            console.log('老弟,你走了!Index页面')
        }
    })
    return <h2>JSPang.com</h2>;
  }

return的第二个参数意思是:当里面变量的值改变时,才启动return的功能,即解绑功能。如下:

function Example(){
    const [ count , setCount ] = useState(0);

    useEffect(()=>{
        console.log(`useEffect=>You clicked ${count} times`)

        return ()=>{
            console.log('====================')
        }
    },[count])  //关键代码

    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={()=>{setCount(count+1)}}>click me</button>

            <Router>
                <ul>
                    <li> <Link to="/">首页</Link> </li>
                    <li><Link to="/list/">列表</Link> </li>
                </ul>
                <Route path="/" exact component={Index} />
                <Route path="/list/" component={List} />
            </Router>
        </div>
    )
}

useContext让父子传值更简单,对它所包含的组件树提供全局共享数据的一种技术。需要注意的是useContextredux的作用域是不同的,一个解决的是组件之间值传递的问题,一个是应用中统一管理状态的问题,但通过和useReducer的配合使用,可以实现类似Redux的作用。

用法也很简单,先为对应的变量创造上下文,在标签里调用:
import React, { useState , createContext } from ‘react’;
//===关键代码
const CountContext = createContext()

function Example4(){
const [ count , setCount ] = useState(0);

return (
    <div>
        <p>You clicked {count} times</p>
        <button onClick={()=>{setCount(count+1)}}>click me</button>
        {/*======关键代码 */}
        <CountContext.Provider value={count}>
            <Counter />  //子组件
        </CountContext.Provider>

    </div>
)

}
export default Example4;

子组件用use调用即可:

function Counter(){
    const count = useContext(CountContext)  //一句话就可以得到count
    return (<h2>{count}</h2>)
}

useReducer:也是reacthook自带的函数,让代码有更好的可读性和可维护性,给测试提供方便,下面给个最简单的例子:一个参数是状态,一个是控制状态的参数。

function countReducer(state, action) {
switch(action.type) {
case ‘add’:
return state + 1;
case ‘sub’:
return state - 1;
default:
return state;
}
}

  • 从理论层面讨论usecontext和usereducer代替redux的可能:
  • useContext:可访问全局状态,避免一层层的传递状态。这符合Redux其中的一项规则,就是状态全局化,并能统一管理。
  • useReducer:通过action的传递,更新复杂逻辑的状态,主要是可以实现类似Redux中的Reducer部分,实现业务逻辑的可行性。

useMomo优化性能:因为失去shouldcomponentupdate这个生命周期函数,前文提到这个函数可用于性能优化,当返回true时,才更新组件。而且在函数组件里不再区分挂载(mount)和更新(update)两个状态,所以每次都是执行内部的全部逻辑,这样会导致极大的性能浪费。

useMemo(()=>changeXiaohong(name),[name])

只有当第二个参数匹配成功,才会执行。

useref:有两个作用1.获取jsx里的dom元素;2.可用来保存变量,其实用usecontext完全可以代替。


自定义hook函数和创建组件很相似,前者偏向于功能,后者偏向于界面和业务逻辑,以use开头:每次修改状态的方法onResize;useCallback(),目的是为了缓存方法,用useeffect来注册resize来监听时间。
function useWinSize(){
const [ size , setSize] = useState({
width:document.documentElement.clientWidth,
height:document.documentElement.clientHeight
})

const onResize = useCallback(()=>{
    setSize({
        width: document.documentElement.clientWidth,
        height: document.documentElement.clientHeight
    })
},[]) 
useEffect(()=>{
    window.addEventListener('resize',onResize)
    return ()=>{
        window.removeEventListener('resize',onResize)
    }
},[])

return size;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值