Solidjs status update
const context = []; function subscribe(running, subscriptions) { subscriptions.add(running); running.dependencies.add(subscriptions); } export function createSignal(value) { const subscriptions = new Set(); const read = () => { const running = context[context.length - 1]; if (running) subscribe(running, subscriptions); return value; }; const write = (nextValue) => { value = nextValue; for (const sub of [...subscriptions]) { sub.execute(); }}; return [read, write]; } function cleanup(running) { for (const dep of running.dependencies) { dep.delete(running); } running.dependencies.clear(); } export function createEffect(fn) { const execute = () => { cleanup(running); context.push(running); try { fn(); } finally { context.pop(); }}; const running = { execute, dependencies: new Set() }; execute(); } export function createMemo(fn) { const [s, set] = createSignal(); createEffect(() => set(fn())); return s; }Copy the code
Add a batch update function
function flush(fn) {
  if (typeof MessageChannel !== undefined) {
    const { port1, port2 } = new MessageChannel();
    port1.onmessage = fn;
    port2.postMessage(null);
  } else {
    setTimeout(fn);
  }
}
Copy the code
Using the update principles above, we can encapsulate a state management application in React
export function createStore(initState) { const createSetter = {}; const stateKeys = Object.keys(initState); for (let i = 0; i < stateKeys.length; i++) { const [get, set] = createSignal(initState[stateKeys[i]]); createSetter[stateKeys[i]] = {get,set} } const dispatch = (state) => { const dispatchKeys = Object.keys(state); dispatchKeys.forEach(item => createSetter[item].set(state[item])); } const getStore = () => Object.keys(createSetter).reduce((pre,cur) => { pre[cur] = createSetter[cur].get(); return pre; }, {}) const useStore = (stateKeys) => { const [, forceUpdate] = useState({}); const updateRef = useRef(false); const queue = useRef(0); useEffect(() => { createEffect(() => { stateKeys.forEach(item => { createSetter[item].get() }); if (updateRef.current) { queue.current += 1; queue.current === 1 && flush(() => { queue.current = 0; forceUpdate({}); }) } else { updateRef.current = true; }}); } []); return getStore() } return { useStore, getStore, dispatch }; }Copy the code
A small example of using the above state management

const { useStore, getStore, dispatch } = createStore({
  count: 0,
  grade: 0,
  num: 0,
});

const handleAdd = () => {
  const { count, grade, num } = getStore();
  Promise.resolve().then(() => {
    dispatch({
      count: count+1,
      grade: grade+1,
      num: num + 1,
    })
  })
}

const handleGrade = () => {
  const { grade } = getStore();
  dispatch({
    grade: grade+1,
  })
}

function Counter() {
  const { count, grade } = useStore(['count', 'grade']);

  console.log(count, 'render----123count')
  return (
    <div>
      <div>{count}-count</div>
      <div>{grade}-grade</div>
      <div onClick={handleAdd}>add</div>
    </div>
  );
}

function Grade() {
  const { grade, num } = useStore(['grade', 'num']);

  console.log(grade, 'render----123grade')
  return (
    <div>
      <div>{grade}-grade</div>
      <div>{num}-num</div>
      <div onClick={handleGrade}>grade</div>
    </div>
  );
}

function App() {
  return (
    <div className="App">
     <Counter />
     <Grade />
    </div>
  );
}

Copy the code

From the above example, we can see that each component only cares about its own data, irrelevant data update, does not cause its own component rerender😊