React + hook
hook简介
hook是React 16.8的新增特性。它可以让你在不编写 class 的情况下使用 state以及其他的React特性。
为什么要用hook
它可以让函数组件也拥有类组件的特性。
它能为你解决那些问题
解决函数组件的一些不足:
1、无法定义状态。
利用useState。可以为函数组件声明状态
2、没有生命周期。
利用useEffect。可以模仿类组件的声明周期:
componentDidMount,
componentDidUpdata,
componentWillUnmount
下面是hook的一些API
常用API及使用方法
useState
让无状态组件拥有状态
//从react中解构useState
import {useState} from 'react';
function App() {
//声明一个数组 数组中的值为:[ ‘变量名’,'修改变量的函数' ]
//修改变量的函数 必须以set开头,并且用驼峰命名
const [cont,setCont]=useState(1)
return (
<div className="App">
<header className="App-header">
{cont}
//通过事件触发 setCont(‘any’)
<button
onClick={()=>{setCont(cont+1)}}
>
+++
</button>
</header>
</div>
);
}
export default App;
useEffect
副作用函数
//从react中解构 useEffect
import { useEffect } from 'react';
function App() {
/* effect使用方法
useEffect('回调函数','依赖列表:可以不传')
effect的四种状态
1、 不传依赖表
useEffect(()=>{ console.log('张涛'); })
2、 传入空依赖表。类似于componentDidMount
useEffect(()=>{ console.log('张涛'); },[])
3、 传入依赖表,并且依赖一个变量,类似于componentDidUpData
useEffect(()=>{ console.log('张涛'); },[cont])
3、 返回一个函数类似于 componentWillUnmount
useEffect(()=>{ console.log('张涛'); return()=> {}; },[])
*/
useEffect(()=>{ console.log('张涛'); })
return (
<div className="App">
<header className="App-header">
{cont}
<button onClick={()=>{setCont(cont+1)}}> +++ </button>
</header>
</div>
);
}
export default App;
useContext
跨组件传值
//从react中解构 useContext
import { useContext } from 'react';
//用于跨组件传值,类似于createContext
const themes = {
light: {
foreground: "#000000",
background: "#eeeeee"
},
dark: {
foreground: "#ffffff",
background: "#222222"
}
};
//声明跨组件传值 const ThemeContext = React.createContext(themes.light);
function App() {
return (
//ThemeContext.Provider 作为提供方 传入一个value
<ThemeContext.Provider value={themes.dark}>
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
function ThemedButton() {
//接受提供方传过来的 value
const theme = useContext(ThemeContext);
return (
<button style={{ background: theme.background, color: theme.foreground }}>
I am styled by theme context!
</button>
);
}
额外的 hook API 及使用方法
useReducer
小型redux
//从react中解构 useReducer
import { useReducer } from 'react';
//定义仓库状态
const initialState = {count: 0};
//定义修改状态的函数
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default: throw new Error();
}
}
function Counter() {
/* 使用方法 声明一个数组 = useReducer( '改变状态的函数','仓库状态/初始化数据' )
const [ state,dispatch ]=userReducer(reducer,initialState)
*/
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
useCallback
给予依赖后类似于shouldComponentUpdate
//从react中解构 useCallback
import { useCallback } from 'react';
//useCallback 有返回值 返回一个函数
// 在依赖数据修改时才会触发事件。官方介绍类似于shouldComponentUpdate
const memoizedCallback = useCallback( () => { doSomething(a, b); }, [a, b], );
useMemo
类似于Vue中的计算属性
//从react中解构 useMemo
import { useMemo } from 'react';
// useMemo有返回值 返回一个新的值
//使用方法 声明一个变量 = useMemo('毁掉函数',依赖列表 || null)
//类似于Vue中的计算属性 判断依赖是否更新,更新执行函数 不更新不做改变
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
useRef
获取dom
//从react中解构 useRef
import { useRef } from 'react';
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` 指向已挂载到 DOM 上的文本输入元素
inputEl.current.focus(); };
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
hook优缺点
hook的优点:
我认为是让我们可以更好的利用函数组件去做一些事情。相比于类组件减少了很多代码,让整个组件看起来不是很乱。同时也不需要考虑this指向的问题。
有优点一定就会有缺点嘛,下面就是hook的缺点
hook的缺点: 我认为hook的缺点就是声明周期不够完善,不如class组件那么灵活还有比如 useRef在使用哦时也不如直接使用ref(自我感觉)。
总结
比起用函数组件 + hook 我更习惯于用class,尽管代码量和代码的阅读体验不是很好,但是类组件是真的香。