React Hooks 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

前言

本篇主要以讲几个常用的api为主。

1.useState

这个例子用来显示一个计数器。当你点击按钮,计数器的值就会增加,现在我们的写法如下,

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

这是我们所熟悉的写法,替换成useState后

import React, { useState } from 'react';

function Example() {
// 声明一个叫 "count" 的 state 变量
const [count, setCount] = useState(0); return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
  • 1.首先通过在函数组件里调用useState()来给组件添加一些内部 state,(React 会在重复渲染时保留这个 state)。
  • 2.useState()可以传入一个参数,传入的参数就是初始的state,在上面例子当中,0就是初始值。【这个初始 state 参数只有在第一次渲染的会被用到。】
  • 3.useState() 会返回一对值:当前状态和一个让你更新它的函数(你可以在事件处理函数中或其他一些地方调用这个函数,它类似 class 组件的 this.setState,但是它不会把新的 state 和旧的 state 进行合并。)
  • 4.可以通过useState声明多个state变量,如下
function ExampleWithManyStates() {
// 声明多个 state 变量!
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
// ...
}

2.useEffect

useEffect 就是一个 Effect Hook,给函数组件增加了操作副作用的能力。它跟 class 组件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount 具有相同的用途,只不过被合并成了一个 API。

依然是先上例子

class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
} componentDidMount() {
document.title = `You clicked ${this.state.count} times`;
} componentDidUpdate() {
document.title = `You clicked ${this.state.count} times`;
} render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
import React, { useState, useEffect } from 'react';

function Example() {
const [count, setCount] = useState(0); // 相当于 componentDidMount 和 componentDidUpdate:
useEffect(() => {
document.title = `You clicked ${this.state.count} times`;
}); return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
  • 1.默认情况下,React 会在每次渲染后调用副作用函数 —— 包括第一次渲染的时候。

  • 2.副作用函数还可以通过返回一个函数来指定如何“清除”副作用。它的执行顺序是,每次页面更新前,先执行return的函数,然后在执行useEffect里面的内容。

import React, { useState, useEffect } from 'react';

function Example() {

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

  useEffect(() => {
console.log(`You clicked ${count} times`);
return () => {
console.log('每次页面更新前,我会先被执行');
}
}); return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
  • 3.跟 useState 一样,你可以在组件中多次使用 useEffect,因此通过使用 Hook,你可以把组件内相关的副作用组织在一起(例如创建订阅及取消订阅),而不要把它们拆分到不同的生命周期函数里。
  • 4.useEffect还可以传入第二个参数,指定当某个值发生变化的时候,才触发副作用.
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // 仅在 count 更改时更新
  • 5.如果想执行只运行一次的 effect(仅在组件挂载和卸载时执行),可以传递一个空数组([])作为第二个参数。

3.useReducer

useState 的替代方案。它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法。(如果你熟悉 Redux 的话,就已经知道它如何工作了。)

// reducer.js
export const initialState = {count: 0}; export default (state, action) => {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
} // Counter.js
import React, { useReducer } from 'react';
import reducer, { initalState } from './reducer.js'; function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
</div>
);
}

4.useContext

接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。当前的 context 值由上层组件中距离当前组件最近的 <MyContext.Provider> 的 value prop 决定。

具体使用查看这篇文章。

React Hooks新特性学习随笔的更多相关文章

  1. 使用React Hooks新特性useReducer、useContext替代传统Redux高阶组件案例

    当我们使用redux进行数据管理的时候,一般都是在根组件通过Provider的方式引入store,然后在每个子组件中,通过connect的方式使用高阶组件进行连接,这样造成的一个问题是,大量的高阶组件 ...

  2. ES7/8新特性学习随笔

    随着每年EcmaScript都会为js带来一些新特性,带来更多美化的编程体验,今天就走进一下es2016/2017所带来的新特性 ES7新特性 includes() 指数操作符 ES8新特性 asyn ...

  3. JavaScript ES6 数组新方法 学习随笔

    JavaScript ES6 数组新方法 学习随笔 新建数组 var arr = [1, 2, 2, 3, 4] includes 方法 includes 查找数组有无该参数 有返回true var ...

  4. Java8 新特性学习 Lambda表达式 和 Stream 用法案例

    Java8 新特性学习 Lambda表达式 和 Stream 用法案例 学习参考文章: https://www.cnblogs.com/coprince/p/8692972.html 1.使用lamb ...

  5. java8 新特性学习笔记

    Java8新特性 学习笔记 1主要内容 Lambda 表达式 函数式接口 方法引用与构造器引用 Stream API 接口中的默认方法与静态方法 新时间日期 API 其他新特性 2 简洁 速度更快 修 ...

  6. QQ音乐:React v16 新特性实践

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由QQ音乐技术团队发表于云+社区专栏 自从去年9月份 React 团队发布了 v16.0 版本开始,到18年3月刚发布的 v16.3 版 ...

  7. java8新特性学习1

    java8增加了不少新特性,下面就一些常见的新特性进行学习... 1.接口中的方法 2.函数式接口 3.Lambda表达式 4.java8内置的四大核心函数式接口 5.方法引用和构造器引用 6.Str ...

  8. java8新特性学习:函数式接口

    本文概要 什么是函数式接口? 如何定义函数式接口? 常用的函数式接口 函数式接口语法注意事项 总结 1. 什么是函数式接口? 函数式接口其实本质上还是一个接口,但是它是一种特殊的接口:SAM类型的接口 ...

  9. java8新特性学习:stream与lambda

    Streams api 对 Stream 的使用就是实现一个 filter-map-reduce 过程,产生一个最终结果,或者导致一个副作用(side effect). 流的操作类型分为两种: Int ...

随机推荐

  1. mysql、mybatis遇到问题集合

    1.错误描述 使用JDBC连接MySql时出现:The server time zone value '�й���׼ʱ��' is unrecognized or represents more th ...

  2. 调试技巧 ------ printf 的使用技巧

    编译器宏:__FUNCTION__,__FILE__,__LINE__ #define __debug #ifdef __debug //#define debug(format,...) print ...

  3. P2889 [USACO07NOV]挤奶的时间Milking Time

    P2889 [USACO07NOV]挤奶的时间Milking Time 奶牛Bessie在0~N时间段产奶.农夫约翰有M个时间段可以挤奶,时间段f,t内Bessie能挤到的牛奶量e.奶牛产奶后需要休息 ...

  4. 鸟哥的Linux私房菜——第十一章

    视频链接: 土豆:http://www.tudou.com/programs/view/yT0PfIWU720 B站(推荐): http://www.bilibili.com/video/av9877 ...

  5. 数学:拓展Lucas定理

    拓展Lucas定理解决大组合数取模并且模数为任意数的情况 大概的思路是把模数用唯一分解定理拆开之后然后去做 然后要解决的一个子问题是求模质数的k次方 将分母部分转化成逆元再去做就好了 这里贴一份别人的 ...

  6. Github 开源项目(二) jsmpeg-vnc

    参考文章:http://blog.csdn.net/qq_28877125/article/details/70141713 适用于Windows的低延迟,高帧率屏幕共享服务器以及用于浏览器的客户端 ...

  7. JAVA io 包小结

    IO 无非读写 I --> Reader  O--> Writer 为了方便字符 或者 文本文件的 操作创造出了 字符流 尤其是 缓冲字符输入输出流(BufferedReader,Buff ...

  8. java.uti.Random类nextInt方法中随机数种子为47的奇怪问题

    一,问题描述 需要生成一个[0,1]的随机数.即随机生成 0 或者 1.使用java.util.Random类的 nextInt(int)方法,当构造Random类的对象并提供随机数种子时,发现了一个 ...

  9. [整理]Win下好用的Markdown工具

    用过haroopad,MarkPad,Sublime + markdown插件,前2款勉强能用,都处于继续开发中,haroopad支持的语法相对较少,提示也不明显,MarkPad还是有不少bug. 后 ...

  10. centos安装lrzsz

    yum -y install lrzsz 使用rz打开上传框