Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | 14x 14x 30x 154x 14x 154x 46x 46x 37x 13x 13x 13x 13x 13x 13x 107x 107x 12x 50x 49x 49x 49x 1x 48x 48x 27x 3x 27x 27x 27x 27x 28x 27x 27x 27x 27x 2x 19x 19x 19x 19x 19x 19x 19x 19x 19x 19x 19x 30x | import React, { Children } from 'react'
import PropTypes from 'prop-types'
import hasDiff from './hasDiff'
import hasComplex from './hasComplex'
export default class ThroughProvider extends React.Component {
static childContextTypes = {
through: PropTypes.object.isRequired,
}
static propTypes = {
children: PropTypes.element,
}
constructor(props) {
super(props)
this.areas = {}
}
getChildContext() {
return {
through: {
update: this.update,
add: this.add,
remove: this.remove,
subscribe: this.subscribe,
}
}
}
area = (area) => {
if( !Object.prototype.hasOwnProperty.call(this.areas, area) ) {
this.areas[area] = {
name: area,
listeners: [],
counters: {},
data: {},
}
}
return this.areas[area]
}
notify = (area, syncUpdate) => {
area = this.area(area)
area.listeners.forEach(
listener => listener(area.data, syncUpdate)
)
}
subscribe = ( area, listener ) => {
area = this.area(area)
area.listeners.push(listener)
listener(area.data)
return () => {
area.listeners = area.listeners.filter(
item => item !== listener
)
}
}
checkArgs(area, key, props) {
Eif (process.env.NODE_ENV !== 'production') {
if(
!( typeof area === 'string' || area instanceof String ) ||
!( typeof key === 'string' || key instanceof String ) ||
!( props instanceof Object &&
!(props instanceof Array) &&
!(props instanceof Function)
)
) {
throw new Error(
"react-through: type error: " +
"through.[add|update|remove](area:string, key:string, props:Object)"
)
}
}
}
update = (area, key, props, syncUpdate = undefined) => {
this.checkArgs(area, key, props)
area = this.area(area)
Eif (process.env.NODE_ENV !== 'production') {
if( !area.counters[key] ) {
throw new Error("react-through: bearing key must be added before update")
}
}
const prevProps = area.data[key] || {}
if( !hasDiff(prevProps, props) ) return
if( undefined === syncUpdate ) {
syncUpdate = !hasComplex(props)
}
const data = Object.assign({}, area.data)
data[key] = {...props}
area.data = data
this.notify(area.name, syncUpdate)
}
add = (area, key) => {
this.checkArgs(area, key, {})
area = this.area(area)
area.counters[key] = area.counters[key] ? area.counters[key] + 1 : 1
Eif (process.env.NODE_ENV !== 'production') {
if( 2 < area.counters[key] ) {
throw new Error(
"react-through: bearing key adding must be not more 2, call remove()"
)
}
}
}
remove = (area, key) => {
this.checkArgs(area, key, {})
area = this.area(area)
let count = area.counters[key]
count = count ? count - 1 : 0
area.counters[key] = count
Eif( !count && Object.prototype.hasOwnProperty.call(area.data, key) ) {
const data = Object.assign({}, area.data)
delete area.counters[key]
delete data[key]
area.data = data
this.notify(area.name, true)
}
}
render() {
return React.Children.only(this.props.children)
}
}
|