42 lines
		
	
	
		
			1.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
			
		
		
	
	
			42 lines
		
	
	
		
			1.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
| import type { Ref } from 'vue';
 | |
| import { onBeforeUnmount, ref } from 'vue';
 | |
| import wrapperRaf from '../raf';
 | |
| 
 | |
| export type Updater<State> = (prev: State) => State;
 | |
| /**
 | |
|  * Execute code before next frame but async
 | |
|  */
 | |
| export function useLayoutState<State>(
 | |
|   defaultState: State,
 | |
| ): [Ref<State>, (updater: Updater<State>) => void] {
 | |
|   const stateRef = ref(defaultState);
 | |
|   let tempState = stateRef.value;
 | |
| 
 | |
|   let updateBatchRef = [];
 | |
|   const rafRef = ref();
 | |
|   function setFrameState(updater: Updater<State>) {
 | |
|     wrapperRaf.cancel(rafRef.value);
 | |
|     updateBatchRef.push(updater);
 | |
| 
 | |
|     rafRef.value = wrapperRaf(() => {
 | |
|       const prevBatch = updateBatchRef;
 | |
|       // const prevState = stateRef.value;
 | |
|       updateBatchRef = [];
 | |
| 
 | |
|       prevBatch.forEach(batchUpdater => {
 | |
|         tempState = batchUpdater(tempState);
 | |
|       });
 | |
| 
 | |
|       // if (tempState !== stateRef.value) {
 | |
|       stateRef.value = tempState;
 | |
|       // }
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   onBeforeUnmount(() => {
 | |
|     wrapperRaf.cancel(rafRef.value);
 | |
|   });
 | |
| 
 | |
|   return [stateRef as Ref<State>, setFrameState];
 | |
| }
 |