React Hook
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
useState 和 useEffect
useState 会返回一对值:当前状态和一个让你更新它的函数,你可以在事件处理函数中或其他一些地方调用这个函数。
它类似 class 组件的 this.setState,但是它不会把新的 state 和旧的 state 进行合并。
将 useEffect 放在组件内部让我们可以在 effect 中直接访问 count state 变量(或其他 props)。
我们不需要特殊的 API 来读取它 —— 它已经保存在函数作用域中。
案例:
import React, { useState, useEffect } from 'react';
function Hooks () {
const [ count, setCount ] = useState(0)
const [ width, setWidth ] = useState(document.body.clientWidth)
const onChange = () => {
setWidth(document.body.clientWidth)
}
useEffect(() => {
//相当于 componentDidMount
window.addEventListener('resize', onChange, false)
return () => {
//相当于componentWillUnmount
window.removeEventListener('resize', onChange, false)
}
}, [])
useEffect(() => {
//相当于componentDidUpdate
document.title = count;
})
useEffect(() => {
console.log(`count change: count is ${count}`)
}, [ count ])
return (
<div>
页面名称: { count }
页面宽度: { width }
<button onClick={() => { setCount(count + 1)}}>点我</button>
</div>
)
}
// 导出组件
export default Hooks;
useContext
接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。
当前的 context 值由上层组件中距离当前组件最近的 <MyContext.Provider> 的 value prop 决定。
import React, { useContext } from 'react';
const themes = {
light: {
foreground: "#000000",
background: "#eeeeee",
},
dark: {
foreground: "#ffffff",
background: "#222222",
fontSize: "24px"
}
};
const ThemeContext = React.createContext(themes.light);
function Hook3() {
return (
<ThemeContext.Provider value={themes.dark}>
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
function ThemedButton() {
const theme = useContext(ThemeContext);
return (
<button style={{background: theme.background, color: theme.foreground, fontSize: theme.fontSize }}>
I am styled by theme context!
</button>
);
}
// 导出组件
export default Hook3;
useReducer
/*
useReducer的作用类似redux中的功能,相较于useState,useReducer适合一些逻辑较复杂且包含多个子值的情况。
reducer接受两个参数,第一个参数是一个reducer,第二个参数是初始 state,返回值为最新的state和dispatch函数。
按照官方的说法,useReducer适合用于复杂的state操作逻辑,嵌套的state的对象的场景。
*/
import React, { useReducer } from 'react';
function Hook3 () {
const initialState={count:0}
const [count,dispatch] = useReducer((state,avtion) => {
switch(avtion.type) {
case 'add':
return state+1;
case 'minus':
return state-1
default:
return state
}
},0)
return (
<div>
<div>{count}</div>
<button onClick={() => {dispatch({type: 'add'})}}>useReducer加</button>
<button onClick={() => {dispatch({type: 'minus'})}}>useReducer减</button>
</div>
)
}
export default Hook3;
useCallback
/*
useCallback,它将返回该回调函数的 memoized 版本,该回调函数仅在某个依赖项改变时才会更新.
是来优化子组件的,防止子组件的重复渲染
*/
import React, { useState, useCallback, useEffect } from 'react';
function Parent() {
const [count, setCount] = useState(1);
const [val, setVal] = useState('');
const callback = useCallback(() => {
return count;
}, [count]);
return <div>
<h4>父组件:{count}</h4>
<Child callback={callback}/>
<button onClick={() => setCount(count + 1)}>点我+1</button>
</div>;
}
function Child({ callback }) {
const [count, setCount] = useState(() => callback());
useEffect(() => {
setCount(callback());
}, [callback]);
return <div>
子组件:{count}
</div>
}
export default Parent;
useMemo
/*
useMemo: 由于父组件的state发生改变会导致父组件更新,而子组件虽然没有发生改变但是也会进行更新,
优化当前组件主要是通过 memoize 来将一些复杂的计算逻辑进行缓存,其作用类似于类组件的 PureComponent。
会在渲染的时候执行,而不是渲染之后执行,这一点和 useEffect 有区别,所以 useMemo不建议方法中有副作用相关的逻辑
*/
import { useMemo , useState} from 'react';
function Hook3 () {
const [ count, setCount ] = useState(0)
const add = useMemo(() => {
return count + 1
}, [count])
return (
<div>
点击次数: { count }
<br/>
次数加一: { add }
<button onClick={() => { setCount(count + 1)}}>点我</button>
</div>
)
}
export default Hook3;
useRef
/*
useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。
返回的 ref 对象在组件的整个生命周期内持续存在。
*/
import React, { useState, useRef } from 'react'
function Hook3(){
const [count, setCount] = useState(0)
const counterEl = useRef(null)
const increment = () => {
setCount(count + 1)
console.log(counterEl)
}
return (
<>
Count: <span ref={counterEl}>{count}</span>
<button onClick={increment}>Hook3点我+</button>
</>
)
}
export default Hook3;