Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
useState | useReduce 的使用
import React, { useState, useReducer } from 'react'
// 创建reduce
const ageReduce = (state, action) => {
switch (action.type) {
case 'add':
return state + 1
case 'minus':
return state - 1
default:
return state
}
}
const StateReduce = function () {
// 基础数据类型推荐使用useState Number、String、Boolean
const [count, setCount] = useState(0)
// 复杂类型推荐使用useReduce 如 Object、Array 对应的属性更容易操作
const [age, ageDispatch] = useReducer(ageReduce, 0)
const addCount = () => {
// 第一更新种方式
// setCount(count + 1)
// 第二种更新方式
setCount(count => count + 1)
}
/**
* @type 操作类型
*/
const setAge = type => {
ageDispatch({ type })
}
return (
<div>
<div>count:{count}</div>
<button onClick={addCount}>addCount</button>
<div>age:{age}</div>
<button onClick={setAge.bind(this, 'add')}>addAge</button>
<button onClick={setAge.bind(this, 'minus')}>minusAge</button>
</div>
)
}
export default StateReduce
附上视频教程(非原创视频):《useState&useReduce视频教程》
useEffect 的使用
- 你可以把
Hook 看做useEffect
,componentDidMount
和componentDidUpdate
这三个函数的组合。componentWillUnmount
import React, { useState, useEffect } from 'react'
const Effect = function () {
const [count, setCount] = useState(0)
const [other, setOther] = useState(10)
//不传第二个参数时每次更新都会执行
useEffect(() => {
console.log('每次更新都会执行,相当于didmount、didUpdate')
})
//第二个参数为某个属性时当属性改变执行
useEffect(() => {
console.log('Count改变时我出发----count改变了')
}, [count])
useEffect(() => {
console.log('Other改变时我出发----other改变了')
}, [other])
//第二个参数为[]空数组时相当于是初始化执行一次
useEffect(() => {
console.log('只在初始化时候执行,相当于didMount')
}, [])
//返回值相当于销毁 也可用于关闭页面的监听订阅和定时器
useEffect(() => {
return () => {
console.log('我销毁了!-------------------')
}
}, [])
const handleClick = () => {
setCount(count + 2)
}
const handleOtherClick = () => {
setOther(other + 1)
}
return (
<div>
<div>Count:{count}</div>
<button onClick={handleClick}>操作触发Count</button>
<div>Other:{other}</div>
<button onClick={handleOtherClick}>操作触发Other</button>
</div>
)
}
export default Effect
附上视频教程(非原创视频):《useEffect视频教程》
useContext 的使用
import React, { Component, createContext, useContext } from 'react'
const AppContext = createContext()
export default function Context() {
return (
<AppContext.Provider
value={{
context: '测试数据',
location: '我来自父组件的context',
}}
>
<Foo />
<Bar />
<Baz />
</AppContext.Provider>
)
}
/**
* 类组件的调用方法:
* @Foo 原始的标签调用方式 使用 AppContext.Consumer 通过返回值拿到。
* @Bar 使用static接收 是标签的简化版更方便操作。
* 函数组件的使用:
* @Baz 函数hook方法或比较简洁清爽。
*/
class Foo extends Component {
render() {
return (
<AppContext.Consumer>
{value => (
<div>
类组件标签获取方法:{value.context}、{value.location}
</div>
)}
</AppContext.Consumer>
)
}
}
class Bar extends Component {
static contextType = AppContext
render() {
const { context, location } = this.context
return (
<div>
类组件通过static获取:{context}、{location}
</div>
)
}
}
function Baz() {
const { context, location } = useContext(AppContext)
return (
<div>
useContext函数获取:{context}、{location}
</div>
)
}
附上视频教程(非原创视频):《useContext视频教程》
useRef 的使用
import React, { Component, createRef, useRef, forwardRef } from 'react'
export default function Ref () {
const inputRef = useRef()
// 父组件的ref 子组件绑定 forwardRef 就能获取子组件的Ref
const focusInput = () => {
console.log(inputRef.current)
inputRef.current.focus()
}
return (
<div>
<Foo />
<CreateRefFoo />
<FooFunc ref={inputRef} />
<button onClick={focusInput}>父组件聚焦useRef</button>
</div>
)
}
/**
* 类组件获取ref
* @Foo 类组件获取ref
* @CreateRefFoo 通过 createRef 来获取
* @FooFunc 函数组件获取ref
* @forwardRef 转发Ref
*/
class Foo extends Component {
refInput = input => {
this.inputRef = input
}
focusInput = () => {
this.inputRef.focus()
}
render() {
return (
<div>
<input ref={this.refInput} />
<button onClick={this.focusInput}>聚焦Component</button>
</div>
)
}
}
class CreateRefFoo extends Component {
inputRef = createRef()
focusInput = () => {
this.inputRef.current.focus()
}
render() {
return (
<div>
<input ref={this.inputRef} />
<button onClick={this.focusInput}>聚焦Component-createRef</button>
</div>
)
}
}
//forwardRef 转发Ref
const FooFunc = forwardRef((props,inputRef) =>{
// const inputRef = useRef()
const focusInput = () => {
inputRef.current.focus()
}
return (
<div>
<input ref={inputRef} />
<button onClick={focusInput}>聚焦useRef</button>
</div>
)
}
)
附上视频教程(非原创视频):《useRef视频教程》
useCallback | useMemo 的使用和区别
import React, { useState, useCallback, useMemo, PureComponent, memo } from 'react'
/**
* 作用区别 @PureComponent === @memo 用于组件的优化使用
* @useCallback @useMemo 区别在于返回值上 用于固定值或者固定函数引用传给子组件 都可用于初次渲染
* useCallback(fn, deps) 相当于 useMemo(() => fn, deps)。
* @useCallback 返回一个函数方法
* @useMemo 返回一个函数执行完成的值
*/
const List = memo(props => {
console.log('renderList')
return (
<div>
{props.count}
<url>{props.render}</url>
</div>
)
})
class FooList extends PureComponent {
render() {
console.log('renderFooList')
return <div>{this.props.count}</div>
}
}
const CallbackMemo = props => {
const [range, setRange] = useState({ min: 0, max: 1000 })
const [count, setCount] = useState(0)
// const render = useCallback(() => {
// let list = []
// for (let i = 0; i < range.max; i++) {
// list.push(<li key={i}>{i}</li>)
// }
// return list
// }, [range])
const render = useMemo(() => {
let list = []
for (let i = 0; i < range.max; i++) {
list.push(<li key={i}>{i}</li>)
}
return list
}, [range])
return (
<div>
<h1>{count}</h1>
<button onClick={() => setCount(count + 1)}>setCount</button>
<button onClick={() => setRange(range => ({ ...range, max: range.max + 1 }))}>
setRange
</button>
<List count={1} render={render} />
<FooList count={1} />
</div>
)
}
export default CallbackMemo
附上视频教程(非原创视频):《useCallback & useMemo 视频教程》