Immutable.js出自Facebook,是最流行的不可变数据结构的实现之一。它实现了完全的持久化数据结构,使用结构共享。所有的更新操作都会返回新的值,但是在内部结构是共享的,来减少内存占用。Immutablejs官网
在上一篇介绍redux的文章,我们可以看到在创建的reducer中进行数据更改的时候,会使用...来复制状态数据,为的就是不对原数据进行直接修改,只做替换,就是为了实现react的数据不可变immutable。也就是说如果state的数据比较简单那还好,万一比较复杂,就要复制很多这样的结构数据,很占内存影响app的性能。
安装
bash
npm i immutable redux-immutable -S
替换redux
中的combineReducers
,改用redux-immutable
里面的
js
import { createStore } from "redux";
import { combineReducers } from "redux-immutable";
import { CounterReducer } from "./CounterReducer";
const reducers = combineReducers({
count: CounterReducer,
});
let store = createStore(reducers);
store.subscribe(() => console.log(store.getState()));
export default store;
改造reducers里面的代码
js
import { fromJS } from "immutable";
const initialState = fromJS({
counter: 0,
userInfo: {
name: "John Doe",
age: 25,
},
});
function CounterReducer(state = initialState, action) {
switch (action.type) {
case "ADD":
return state.update("counter", (val) => {
console.log("🚀 ~ returnstate.update ~ val:", val);
return val + 1;
});
case "DEC":
return state.update('counter',value => value - 1)
default:
return state;
}
}
export { CounterReducer };
组件里面使用方式变化
DemoA.js
js
import store from "../../store";
function DemoA() {
const count = store.getState().get("count").get("counter");
return (
<div>
<p> Demo A count: {count}</p>
</div>
);
}
export default DemoA;
DemoB.js
js
import store from "../../store";
function DemoB() {
const data = store.getState().get("count");
return (
<div>
<p>Demo B</p>
<div>
<span>name: {data.getIn(["userInfo", "name"])}</span> <br />
<span>age: {data.getIn(["userInfo", "age"])}</span>
<span>count:{data.get("counter")}</span>
</div>
<button onClick={() => store.dispatch({ type: "ADD" })}>add count</button>
</div>
);
}
export default DemoB;
index.js
js
import DemoA from "./DemoA";
import DemoB from "./DemoB";
import store from "../../store/index";
import { useEffect, useState } from "react";
function Redux() {
console.log(store.getState(), "store.getState()");
const [counter, setCount] = useState(
store.getState().get("count").get("counter")
);
useEffect(() => {
const unsubscribe = store.subscribe(() => {
console.log("aaaa");
setCount(store.getState().get("count").get("counter"));
});
return () => {
unsubscribe();
};
}, [counter]);
return (
<div>
Redux
<hr />
parent count:{counter}
<DemoA />
<DemoB />
</div>
);
}
export default Redux;
实现了同样的效果