什么是immutable
Immutable Data 就是一旦创建,就不能再被更改的数据。对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象。Immutable 实现的原理是 Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗,Immutable 使用了 Structural Sharing(结构共享),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。
其中有 3 种最重要的数据结构:
Map:键值对集合,对应于 Object,ES6 也有专门的 Map 对象
List:有序可重复的列表,对应于 Array
Set:无序且不可重复的列表
immutable 和 React、Redux 结合
使用步骤
1. 安装并引入 redux-immutable
安装: npm i redux-immutable -save
yarn add redux-immutable -s
引入:
import {combineReducers} from 'redux-immutable'
2. 初始化reducer
const rootReducer = combineReducers({
cart
})
// state 必须是 immutable 类型
function cart (state, action){
...
}
3. mapStateToProps 的 state 也是 immutable 类型,使用时应该使用 get 方法
详细代码
App.js 中的代码如下:
import React, { Component } from 'react';
import './App.css';
import CartInfo from './CartInfo';
import InputBar from './InputBar';
class App extends Component {
render(){
return (
<div className="App">
<InputBar />
<hr />
<CartInfo />
</div>
);
}
}
export default App;
CartInfo.js 中的代码如下:
import React, { Component } from 'react'
import { is } from 'immutable'
import { connect } from 'react-redux'
class CartInfo extends Component {
shouldComponentUpdate(nextProps) {
// 如果下一个 props 与当前的 props 不相等时再刷新
// return !nextProps.cart.equals(this.props.cart)
return !is(nextProps.cart, this.props.cart)
}
render() {
const lis = []
// console.log('保存成功')
// immutable 类型的数据循环时使用 forEach
this.props.cart.forEach((v, k) => {
lis.push(
<li key={k}>商品名:{k} 数量:{v}</li>
)
});
return (
<ul>
{lis}
</ul>
)
}
}
// 接收 参数 cart
const mapStateToProps = (state) =>({
cart: state.get('cart')
})
// 加强组件 CartInfo,通过 mapStateToProps 接收到传递进来的参数
export default connect (mapStateToProps)(CartInfo)
InputBar.js 中的代码如下:
import React, { Component } from 'react'
import { connect } from 'react-redux'
class InputBar extends Component {
save = () =>{
const goods_name = this.refs.goods_name.value
const count = this.refs.count.value
this.props.saveToCart({
goods_name,
count
})
}
render() {
return (
<div>
商品:<input type='text' ref='goods_name'></input><br></br>
数量:<input type='number' ref='count'></input><br></br>
<button onClick={this.save}>保存</button>
</div>
)
}
}
// 传递参数,通过 action 的类型,判断此时要进行什么样的操作,将数据处理后以json的形式传递出去
const mapDispatchToProps = (dispatch) =>({
saveToCart : function(json){
dispatch({
type: 'SAVE_TO_CART',
payload: json
})
}
})
// 加强组件 InputBar,通过 mapDispatchToProps 将处理后的数据发送出去
export default connect(null, mapDispatchToProps)(InputBar)
index.js 中的代码如下:
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { combineReducers } from 'redux-immutable'
import { legacy_createStore as createStore} from 'redux'
import { Map } from 'immutable'
import { Provider} from 'react-redux'
const cart = (state = Map({}), action) => {
// 传入的类型须是immutable类型,state 必须初始化
switch (action.type) {
case 'SAVE_TO_CART':
return state.set(action.payload.goods_name, action.payload.count)
default:
return state
}
}
const reducers = combineReducers({
cart
})
const store = createStore(reducers)
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
store.subscribe(() => {
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
})