functioncreateStore(reducer){let listeners=[]let state =1return{
dispatch:(action)=>{
state =reducer(state,action)
listeners.forEach((fn)=>fn())},
getState:()=>state,
subscribe:(listener)=>{
listeners.push(listener)return()=>listeners = listeners.filter((item)=>item!=listener)}}}functionreducer(state,action){switch(action.type){case'ADD':return++state;case'MINUS':return--state;}}let ins =createStore(reducer)let x =ins.subscribe(()=>{
console.log(ins.getState());})
ins.dispatch({type:'ADD'})
ins.dispatch({type:'MINUS'})
functioncreateStore(reducer,initialState){let listeners=[]let state = initialState
return{
dispatch:(action)=>{
state =reducer(state,action)
listeners.forEach((fn)=>fn())},
getState:()=>state,
subscribe:(listener)=>{
listeners.push(listener)return()=>listeners = listeners.filter((item)=>item!=listener)}}}functionreducer(state,action){switch(action.type){case'ADD':return{...state,count:state.count+action.payload
};case'MINUS':return{...state,count:state.count-action.payload
};}return state
}let store =createStore(reducer,{count:1})let x =store.subscribe(()=>{
console.log(store.getState());})
store.dispatch({type:'ADD',payload:5})//{count:6}
store.dispatch({type:'MINUS',payload:2})//{count:4}
这里还有个问题,就是写字符串容易写错,所以我们可以把action改成函数形式:
let action ={add(payload){return{type:'ADD',payload:payload}},minus(payload){return{type:'MINUS',payload:payload}}}let store =createStore(reducer,{count:1})let x =store.subscribe(()=>{
console.log(store.getState());})
store.dispatch(action.add(5))//{count:6}
store.dispatch(action.minus(2))//{count:4}
let action ={add(payload){return{type:'ADD',payload:payload}},minus(payload){return{type:'MINUS',payload:payload}}}functionbindActionCreators(actionCreators,dispatch){let boundActionCreators={}for(let key in actionCreators){
boundActionCreators[key]=function(...args){returndispatch(actionCreators[key](...args))}}return boundActionCreators
}let store =createStore(reducer,{count:1})let x =store.subscribe(()=>{
console.log(store.getState());})let bindAction =bindActionCreators(action,store.dispatch)
bindAction.add(8)
bindAction.minus(2)
function mountState<S>(
initialState:(()=>S)|S,):[S, Dispatch<BasicStateAction<S>>]{const hook =mountWorkInProgressHook();if(typeof initialState ==='function'){
initialState =initialState();}
hook.memoizedState = hook.baseState = initialState;const queue =(hook.queue ={
pending:null,
dispatch:null,
lastRenderedReducer: basicStateReducer,
lastRenderedState:(initialState: any),});const dispatch: Dispatch<
BasicStateAction<S>,>=(queue.dispatch =(dispatchAction.bind(null,
currentlyRenderingFiber,
queue,): any));return[hook.memoizedState, dispatch];}function updateState<S>(
initialState:(()=>S)|S,):[S, Dispatch<BasicStateAction<S>>]{returnupdateReducer(basicStateReducer,(initialState: any));}function updateReducer<S,I,A>(
reducer:(S,A)=>S,
initialArg:I,
init?:I=>S,):[S, Dispatch<A>]{const hook =updateWorkInProgressHook();const queue = hook.queue;invariant(
queue !==null,'Should have a queue. This is likely a bug in React. Please file an issue.',);
queue.lastRenderedReducer = reducer;if(numberOfReRenders >0){// This is a re-render. Apply the new render phase updates to the previous// work-in-progress hook.const dispatch: Dispatch<A>=(queue.dispatch: any);if(renderPhaseUpdates !==null){// Render phase updates are stored in a map of queue -> linked listconst firstRenderPhaseUpdate = renderPhaseUpdates.get(queue);if(firstRenderPhaseUpdate !== undefined){
renderPhaseUpdates.delete(queue);let newState = hook.memoizedState;let update = firstRenderPhaseUpdate;do{// Process this render phase update. We don't have to check the// priority because it will always be the same as the current// render's.const action = update.action;
newState =reducer(newState, action);
update = update.next;}while(update !==null);// Mark that the fiber performed work, but only if the new state is// different from the current state.if(!is(newState, hook.memoizedState)){markWorkInProgressReceivedUpdate();}
hook.memoizedState = newState;// Don't persist the state accumulated from the render phase updates to// the base state unless the queue is empty.// TODO: Not sure if this is the desired semantics, but it's what we// do for gDSFP. I can't remember why.if(hook.baseQueue ===null){
hook.baseState = newState;}
queue.lastRenderedState = newState;return[newState, dispatch];}}return[hook.memoizedState, dispatch];}