示例
示例
直接上代码
1. reducer.js
import React from "react";
import _originalUpdate from "immutability-helper";
export const TestDispatch = React.createContext(null);
export const Actions = {
/**
* 修改数据
*/
CHANGE: "CHANGE",
/**
* 撤销数据
*/
UNDO: "UNDO",
/**
* 恢复数据
*/
REDO: "REDO"
};
const originalUpdate = (state, spec) => {
// _originalUpdate 在不改变原数据的情况下更新数据
const newState = _originalUpdate(state, spec);
if (newState.present) {
window.localStorage.setItem("present", newState.present);
}
return newState;
};
const update = (state, spec) => {
const newPresent = originalUpdate(state.present, Object.assign({}, spec));
return originalUpdate(state, {
past: { $push: [state.present] },
present: { $set: newPresent },
future: { $set: [] }
});
};
const undo = state => {
const lastIndex = state.past.length - 1;
const last = state.past[lastIndex];
const present = state.present;
return originalUpdate(state, {
past: { $splice: [[lastIndex, 1]] },
present: { $set: last },
future: { $unshift: [present] }
});
};
const redo = state => {
const firstFuture = state.future[0];
const present = state.present;
return originalUpdate(state, {
past: { $push: [present] },
present: { $set: firstFuture },
future: { $splice: [[0, 1]] }
});
};
export default (state, { type, payload }) => {
switch (type) {
case Actions.CHANGE: {
return update(state, { value: { $set: payload.value } });
}
case Actions.UNDO: {
return undo(state);
}
case Actions.REDO: {
return redo(state);
}
default:
throw new Error();
}
};
2. App.js
import React, { useReducer } from "react";
import reducer, { Actions, TestDispatch } from "./reducer";
import "./App.css";
export default () => {
const [state, dispatch] = useReducer(reducer, {
past: [],
present: {},
future: []
});
const item = state.present;
const handleUndo = () => {
dispatch({
type: Actions.UNDO
});
};
const handleRedo = () => {
dispatch({
type: Actions.REDO
});
};
const handleChange = e => {
dispatch({
type: Actions.CHANGE,
payload: {
value: e.target.value
}
});
};
return (
<TestDispatch.Provider value={dispatch}>
<div className="App">
<button onClick={handleUndo} disabled={state.past.length === 0}>
撤销
</button>
<button onClick={handleRedo} disabled={state.future.length === 0}>
前进
</button>
<div>
<input value={item.value || ""} onChange={handleChange} />
</div>
</div>
</TestDispatch.Provider>
);
};
网友评论