前言:Hook是raect16.8之后新增的特征,它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。Redux是相关数据处理与状态管理
React的Hooks相关API与Redux事件派发流程
新老生命周期对比
React16.2及之前版本
React16.3之后版本
先看一下class组件的代码
import React from 'react';
import moment from 'moment';
import styles from './index.less';
class ComboInfo extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
iciTag: false,
coverVideoVisible: false,
};
this.isCheckIciTag = false;
}
componentDidMount() {
const { comboInfo = {} } = this.props;
if (comboInfo.id && !this.isCheckIciTag) {
this.checkIciTag();
}
}
componentDidUpdate() {
const { comboInfo = {} } = this.props;
if (comboInfo.id && !this.isCheckIciTag) {
this.checkIciTag();
}
}
render() {
const { onPay, comboInfo, onReceiveCoupon, coupon } = this.props;
const { courseList = [] } = comboInfo;
const { iciTag, coverVideoVisible } = this.state;
return (
<div className={styles.boxMain}>
//其他的DOM结构
</div>
);
}
}
export default ComboInfo;
具有特殊意义 | ------ | 类组件的缺点 |
---|---|---|
①props | – | ①逻辑分散 |
②state | – | ②数据分散 |
③setState | – | ③组件拆分繁琐 |
④render | – | ④state树往往较大 |
⑤生命周期钩子函数 | – | ⑤组件与生命钩子高度耦合 |
Hooks的API
基础Hooks
useState:
该函数将接收先前的 state,并返回一个更新后的值
import React, { useState, useEffect } from 'react';
function Counter() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1)
}
return (
<>
Count: {count}
<button onClick={handleClick}>+</button>
</>
);
}
useEffect
使用useEffect是模拟class组件componentDidMount、componentWillUnmount、componentDidUpdate。当每次的状态state/props的某些值发生变化而进行监听
import React, { useState, useEffect } from 'react';
function Welcome(props) {
useEffect(() => {
document.title = `Hello, ${props.name}`;
}, [props.name]);
return <h1>Hello, {props.name}</h1>;
}
注意事项:
①执行useEffect可能会有副作用( 数据获取,数据订阅,以及手动更改 React 组件中的 DOM 都属于副作用)。并且例如订阅外部数据源,添加DOM事件。这种情况下,清除工作是非常重要的,可以防止引起内存泄露
②useEffect的参数说明:
参数 | 参数类型 | 参数说明 |
---|---|---|
第一个参数 | 函数Functuous | React 组件需要在渲染后执行哪些操作,这个函数会在DOM更新之后被调用。利用第二个参数可控 |
第二个参数 | 数组Array | 依赖state/props的某个值变化而执行,如诺未传参则默认被调用 |
useContext
import React, { useState, useEffect,useContext } from 'react';
const value = useContext(MyContext);
const {Provider, Consumer} = React.createContext(defaultValue);//creatContext结构说明
接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。当前的 context 值由上层组件中距离当前组件最近的 <MyContext.Provider> 的 value prop 决定。(更好的理解:useContext是为了接受较外层的某个值的容器,不需要一层层通过props传递)。
//这是外层需要传递的祖先组件
import React from 'react';
import Page_1 from './pages/Page_1'; //需要传递的后代组件
const deafultContxt = { name: 'youwne'};
export const appContext = React.createContext(deafultContxt);
function App() {
return (
<appContext.Provider value={deafultContxt}>
<Page_1 />
</appContext.Provider>
);
}
export default App;
//需要取祖先组件某个值的后代组件
import React, { useContext } from 'react';
import { appContext } from '../App'; // 引入需要取值的祖先组件
//方式一:
export default function Page1() {
return (
<appContext.Consumer>
{/* 通过 value 来输出你的自定义属性 */}
{({ name }) => <h3>{name}</h3>}
</appContext.Consumer>
);
}
//方式二:
export default function Page1() {
const { name } = useContext(appContext);
return <h3>{name}</h3>;
}
额外的 Hooks
useReducer
const [state, dispatch] = useReducer(reducer, initialArg, init);
useState 的替代方案。它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法。
function init(initialCount) {
return {count: initialCount};
}
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
case 'reset':
return init(action.payload);
default:
throw new Error();
}
}
function Counter({initialCount}) {
const [state, dispatch] = useReducer(reducer, initialCount, init); //init为惰性初始化,可不传
return (
<>
Count: {state.count}
<button
onClick={() => dispatch({type: 'reset', payload: initialCount})}>
Reset
</button>
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
useCallback
把内联回调函数及依赖项数组作为参数传入 useCallback,它将返回该回调函数的 memoized 版本,该回调函数仅在某个依赖项改变时才会更新
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
useMemo
把“创建”函数和依赖项数组作为参数传入 useMemo,它仅会在某个依赖项改变时才重新计算 memoized 值。这种优化有助于避免在每次渲染时都进行高开销的计算。返回一个 memoized 值
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
useRef
const refContainer = useRef(initialValue);
useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内保持不变。
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` 指向已挂载到 DOM 上的文本输入元素
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>输入框获取光标</button>
</>
);
}
注:其他的hooks相关API暂不描述
Redux状态管理
Redux处理流程图例
Redux优点
①单一数据流Stores | ②状态是只读的 | ③状态的改变只能通过纯函数Reducer操作 |
---|