1.useMemo
类似Vue中的计算属性
目前的问题是:当x改变时demo重新执行,方框中的逻辑也会执行,实际我只想当supNum和oppNum变化时执行计算出支持比率
只能作用于函数组件中
import React, { useState, useMemo } from "react";
import { Button } from 'antd';
import './Demo.less';
const Demo = function Demo() {
let [supNum, setSupNum] = useState(10),
[oppNum, setOppNum] = useState(5),
[x, setX] = useState(0);
/*
let xxx = useMemo(callback,[dependencies])
+ 第一次渲染组件的时候,callback会执行
+ 后期只有依赖的状态值发生改变,callback才会再执行
+ 每一次会把callback执行的返回结果赋值给xxx
+ useMemo具备“计算缓存”,在依赖的状态值没有发生改变,callback没有触发执行的时候,xxx获取的是上一次计算出来的结果
和Vue中的计算属性非常的类似!!
*/
let ratio = useMemo(() => {
let total = supNum + oppNum,
ratio = '--';
if (total > 0) ratio = (supNum / total * 100).toFixed(2) + '%';
return ratio;
}, [supNum, oppNum]);
return <div className="vote-box">
<div className="main">
<p>支持人数:{supNum}人</p>
<p>反对人数:{oppNum}人</p>
<p>支持比率:{ratio}</p>
<p>x:{x}</p>
</div>
<div className="footer">
<Button type="primary" onClick={() => setSupNum(supNum + 1)}>支持</Button>
<Button type="primary" danger onClick={() => setOppNum(oppNum + 1)}>反对</Button>
<Button onClick={() => setX(x + 1)}>干点别的事</Button>
</div>
</div>;
};
export default Demo;
2.useCallback
useCallback可以保证函数组件的每一次更新,不再把里面的小函数重新创建,用的都是第一次创建的!
import React, { useState, useCallback } from "react";
import { Button } from 'antd';
import './Demo.less';
/* 子组件 */
/* class Child extends React.PureComponent {
render() {
console.log('Child Render');
return <div>
我是子组件
</div>;
}
} */
const Child = React.memo(function Child(props) {
console.log('Child Render');
return <div>
我是子组件
</div>;
});
/* 父组件 */
// 诉求:当父组件更新的时候,因为传递给子组件的属性仅仅是一个函数「特点:基本应该算是不变的」,所以不想再让子组件也跟着更新了!
// + 第一条:传递给子组件的属性(函数),每一次需要是相同的堆内存地址(是一致的) . 基于useCallback处理!!
// + 第二条:在子组件内部也要做一个处理,验证父组件传递的属性是否发生改变,如果没有变化,则让子组件不能更新,有变化才需要更新 . 继承React.PureComponent即可「在shouldComponentUpdate中对新老属性做了浅比较」!! 函数组件是基于 React.memo 函数,对新老传递的属性做比较,如果不一致,才会把函数组件执行,如果一致,则不让子组件更新!!
const Demo = function Demo() {
let [x, setX] = useState(0);
// const handle = () => { }; //第一次:0x001 第二次:0x101 第三次:0x201 ...
const handle = useCallback(() => { }, []); //第一次:0x001 第二次:0x001 第三次:0x001 ...
return <div className="vote-box">
<Child handle={handle} />
<div className="main">
<p>{x}</p>
</div>
<div className="footer">
<Button type="primary" onClick={() => setX(x + 1)}>累加</Button>
</div>
</div>;
};
3.自定义hook
import React, { useState, useEffect } from "react";
import { Button } from 'antd';
import './Demo.less';
/*
自定义Hook
作用:提取封装一些公共的处理逻辑
玩法:创建一个函数,名字需要是 useXxx ,后期就可以在组件中调用这个方法!
*/
const usePartialState = function usePartialState(initialValue) {
let [state, setState] = useState(initialValue);
// setState:不支持部分状态更改的
// setPartial:我们期望这个方法可以支持部分状态的更改
const setPartial = function setPartial(partialState) {
setState({
...state,
...partialState
});
};
return [state, setPartial];
};
// 自定义Hook,在组件第一次渲染完毕后,统一干点啥事
const useDidMount = function useDidMount(title) {
if (!title) title = 'React系统课';
// 基于React内置的Hook函数,实现需求即可
useEffect(() => {
document.title = title;
}, []);
};
const Demo = function Demo() {
let [state, setPartial] = usePartialState({
supNum: 10,
oppNum: 5
});
const handle = (type) => {
if (type === 'sup') {
setPartial({
supNum: state.supNum + 1
});
return;
}
setPartial({
oppNum: state.oppNum + 1
});
};
useDidMount('哈哈哈哈哈');
return <div className="vote-box">
<div className="main">
<p>支持人数:{state.supNum}人</p>
<p>反对人数:{state.oppNum}人</p>
</div>
<div className="footer">
<Button type="primary" onClick={handle.bind(null, 'sup')}>支持</Button>
<Button type="primary" danger onClick={handle.bind(null, 'opp')}>反对</Button>
</div>
</div>;
};
export default Demo;