memo 组件
掘金https://juejin.cn/post/6844903954539626510
React.memo 为高阶组件。它与React.PureComponent非常相似。
默认情况下其只会对复杂对象做浅层对比。如果父组件更新,使用了memo的子组件可以不更新。
该api使得组件仅在它的 props 发生改变的时候进行重新渲染。通常来说,在组件树中 React 组件,只要有变化就会 走一遍渲染流程。但是通过React.memo(),我们可以仅仅让某些组件进行渲染。
不使用严格模式。
创建文件目录
css 重置
配置别名
安装 yarn add @craco/craco
yarn add @craco/craco
路由配置
引入路由的依赖
创建路由文件
Fragment
React 中一个常见模式是为一个组件返回多个元素。Fragments 可以让你聚合一个子元素列表,并且不在DOM中增加额外节点。
引入redux ![](https://img-blog.csdnimg.cn/31084511b845435883b294cd064f71a9.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAcXFfNDMxMjU5MjE=,size_20,color_FFFFFF,t_70,g_se,x_16)
使用:
// const store = createStore(第一个参数reducer, 第二个参数enhancer 加强的意思对当前store加强); //要合并
// 一个项目中可能有多个reducer 不同页面的数据可以分开成多个reducer。
// 每个页面包含多个数据,每个页面相关的数据放到一个reducer中
新建reducer.js 进入合并reducer
import { combineReducers } from 'redux';
安装 redux 调试工具
// 让浏览器中的redux起作用
// 让浏览器中的redux起作用
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
导出store 进行共享。
把之前引入的store 共享出去
其他地方就可以通过 context 获取state dispatch
// 把redux中的 store 共享出去
import { Provider } from 'react-redux';
<Provider store={store}></Provider>
准备发送网络请求获取数据。
react-redux
核心
- < Provider store>
- connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options]
Provider 内的任何一个组件(比如这里的 Comp),如果需要使用 state 中的数据,就必须是「被 connect 过的」组件——使用 connect 方法对「你编写的组件(MyComp)」进行包装后的产物。
这个函数允许我们将 store 中的数据作为 props 绑定到组件上。
function Recommend(props) {
const { getBannerss } = props;
console.log(props);
// useEffect(() => {
// dispatch(getTopBannerAction());
// }, [dispatch])
useEffect(() => {
// 发送网络请求 执行action // 这里不同**********
getBannerss();
}, [getBannerss])
return (
<RecommendWrapper>
<TopBanner></TopBanner>
<Content>
</Content>
</RecommendWrapper>
)
}
const mapStateToProps = state => ({
// 返回一个对象 state 是最外层的
topBanners: state.recommend.topBanners
});
// 将 action 作为 props 绑定到 MyComp 上。
const mapDispatchToProps = (dispatch) => ({
getBannerss: () => {
// 派发action
dispatch(getTopBannerAction())
}
})
export default connect(mapStateToProps, mapDispatchToProps)(memo(Recommend));
mapStateToProps这个函数允许我们将 store 中的数据作为 props 绑定到组件上。
dispatchProps connect 的第二个参数是 mapDispatchToProps,它的功能是,将 action 作为 props 绑定到 MyComp 上。
使用connect的时候,会进行浅层比较,当数据没有发生改变时,connext包裹的高阶组件,将不会重新渲染。
使用useDispatch(); 作用是直接派发action
使用useSelector 会重新渲染,它返回了一个对象,会根据这个对象进行重新渲染,进行比较的时候是不是浅层比较,直接用了 ===,然而这个函数返回的是一个对象,每次执行这个函数(),通过对象字面量,创建一个新的对象。相当于每次创建的都是一个新的对象,所以是不相等的。(默认是全等,所以是会重新渲染。)
源码
默认 === 比较,会进行重新渲染
使用shallowEqual 可以进行浅层比较。
性能优化2:reducer中数据的修改
// 修改数据事就会进行拷贝,这里拷贝的话会是拷贝整个 state 也就是defaultState 中的全部数据
如果defaultState中的数据发生改变,下面的数据就会重新合并,合并数据一般使用 ... 展开运算符,或者Object.assign,再在后面附上新的值。
尽可能使用原来的数据,会有性能优化。尽可能使用原来数据结构中的节点,来保存这个数据
使用:
使用引号包裹
Immutable.Map() 是把对象浅层的转化为immutable对象。
Immutable.List() 把数组浅层转化为immutable对象。
Immutable.fromJS() 会进行深层的转化。深层的变为immutable对象。
重点是:总是生成新的对象,不会对源对象进行修改,会尽可能的使用源对象的内存空间,进行一个复用,节省性能,节省内存空间。
function Recommend(props) {
// console.log(state);
// 组件redux关联: 获取数据和进行操作
// 第一个参数是回调函数state,要求有一个返回值,作为useSelector的返回值
// 获取redux 中存储的state 可能影响性能
// connect可能进行性能优化
const { topBanners } = useSelector(state => ({
topBanners : state.recommend.topBanners
}), shallowEqual)
// 返回Redux store中对dispatch函数的引用。直接获取dispacth对象
const dispatch = useDispatch();
// 派发action
useEffect(() => {
// 直接派发这个action
dispatch(getTopBannerAction());
}, [dispatch]);
return (
<div>
RecommendP{topBanners.length}
</div>
)
}
export default memo(Recommend);
在项目中使用 Immutable.js
yarn add immutable
在内部数据层级比较少的情况下,使用Map 会浅层的转化为 immutable 数据结构,使用fromJS会深层次的转换,层级比较多,数据包含对象,数组,的时候,数据转变的时候,(如果是深层的修改使用fromJS)
在 reducer 中使用,引入Map 再包裹数据。
import { Map } from 'immutable';
const defaultState = Map({
topBanners: []
})
先安装好这个依赖
yarn add redux-immutable
在导入这个:
// import { combineReducers } from 'redux';
import { combineReducers } from 'redux-immutable';
在组件中使用store中的数据时,因为获取的数据时immutable格式的数据,所以要使用这样的获取方式:
// topBanners : state.recommend.topBanners
topBanners : state.get("recommend").get("topBanners")