Redux Study-- Source Code

Intro

This study base on the 4.0.4 version of Redux, which is implemented by TypeScript.

index.ts

The entrance of the codes, providing all the components API.

isCrushed() used to discover current environment is developing or production environment .

if the code is compressed and under production environment , then isCrushed.name will be type of String but the name will be changed to others

1
2
3
4
5
6
7
8
9
if (
process.env.NODE_ENV !== 'production' &&
typeof isCrushed.name === 'string' &&
isCrushed.name !== 'isCrushed'
) {
warning(
...
)
}

createStore.ts

create store provide several functions

dispatch

dispatch accept an action(which in Type of A) and start running the reducer and get new state

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
function dispatch(action: A) {
if (!isPlainObject(action)) {
throw new Error(
...
)
}

if (typeof action.type === 'undefined') {
throw new Error(
...
)
}

if (isDispatching) {
throw new Error('Reducers may not dispatch actions.')
}

try {
// start running the reducer
isDispatching = true
// the new state comes from current reducer with current state and action
currentState = currentReducer(currentState, action)
} finally {
//finish running the reducer
isDispatching = false
}
/**
* we get the new listeners here and exec them
* currentListeners = nextListeners will ensure if listeners subscribe
* unsubscribe during the exec, the change will happen in next dispatch
*
*/
const listeners = (currentListeners = nextListeners)
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener()
}

return action
}
subscribe

subscribe has a parameter called listener as a callback function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
function subscribe(listener: () => void) {
// listener should be a function
if (typeof listener !== 'function') {
throw new Error('Expected the listener to be a function.')
}

if (isDispatching) {
throw new Error(
...
)
}
//ensure not repeatly unsubscribe
let isSubscribed = true
/**
* This makes a shallow copy of currentListeners so we can use
* nextListeners as a temporary list while dispatching.
*
* This prevents any bugs around consumers calling
* subscribe/unsubscribe in the middle of a dispatch.
*/
ensureCanMutateNextListeners()
// add linstener to nextListeners
nextListeners.push(listener)
// unsubscribe as a return function
return function unsubscribe() {
if (!isSubscribed) {
return
}

if (isDispatching) {
throw new Error(
...
)
}
// mark as unsubscribe
isSubscribed = false
// again prevent buts when unsubscribe using a shallow copy
ensureCanMutateNextListeners()
// get index of the listener we want to unsubscribe
const index = nextListeners.indexOf(listener)
nextListeners.splice(index, 1)
currentListeners = null
}
}
1
2
3
4
5
6
// how to make a shallow copy of current listeners
function ensureCanMutateNextListeners() {
if (nextListeners === currentListeners) {
nextListeners = currentListeners.slice()
}
}
getState

simple as its name, just get the state

1
2
3
4
5
6
7
8
9
function getState(): S {
if (isDispatching) {
throw new Error(
...
)
}

return currentState as S
}
replaceReducer

replace current reducer to get new state

works with

  1. code splitting
  2. hot replacement

todo: more detail analysis

observable

a inter connect point for observable library

# ,
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×