Solidjs狀態更新管理在React中的應用

Solidjs狀態更新
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;
}
複製代碼
添加一個批量更新的函數
function flush(fn) {
  if (typeof MessageChannel !== undefined) {
    const { port1, port2 } = new MessageChannel();
    port1.onmessage = fn;
    port2.postMessage(null);
  } else {
    setTimeout(fn);
  }
}
複製代碼
借用上述更新原理咱們能夠在 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 };
}
複製代碼
利用上述狀態管理一個小例子
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>
  );
}

複製代碼

從上面一個例子中咱們能夠看到每一個組件只關心本身所關心的數據,不相關的數據更新,不會引發自身組件rerender😊

相關文章
相關標籤/搜索