-
-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(deps): inline mini-create-react-context dependency (#9382)
- Loading branch information
Showing
5 changed files
with
186 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// MIT License | ||
// Copyright (c) 2019-present StringEpsilon <[email protected]> | ||
// Copyright (c) 2017-2019 James Kyle <[email protected]> | ||
// https://github.com/StringEpsilon/mini-create-react-context | ||
import React from "react"; | ||
import createReactContext from "./miniCreateReactContext"; | ||
|
||
export default React.createContext || createReactContext; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
175 changes: 175 additions & 0 deletions
175
packages/react-router/modules/miniCreateReactContext.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
// MIT License | ||
// Copyright (c) 2019-present StringEpsilon <[email protected]> | ||
// Copyright (c) 2017-2019 James Kyle <[email protected]> | ||
// https://github.com/StringEpsilon/mini-create-react-context | ||
import React from "react"; | ||
import PropTypes from "prop-types"; | ||
import warning from "tiny-warning"; | ||
|
||
const MAX_SIGNED_31_BIT_INT = 1073741823; | ||
|
||
const commonjsGlobal = | ||
typeof globalThis !== "undefined" // 'global proper' | ||
? // eslint-disable-next-line no-undef | ||
globalThis | ||
: typeof window !== "undefined" | ||
? window // Browser | ||
: typeof global !== "undefined" | ||
? global // node.js | ||
: {}; | ||
|
||
function getUniqueId() { | ||
let key = "__global_unique_id__"; | ||
return (commonjsGlobal[key] = (commonjsGlobal[key] || 0) + 1); | ||
} | ||
|
||
// Inlined Object.is polyfill. | ||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is | ||
function objectIs(x, y) { | ||
if (x === y) { | ||
return x !== 0 || 1 / x === 1 / y; | ||
} else { | ||
// eslint-disable-next-line no-self-compare | ||
return x !== x && y !== y; | ||
} | ||
} | ||
|
||
function createEventEmitter(value) { | ||
let handlers = []; | ||
return { | ||
on(handler) { | ||
handlers.push(handler); | ||
}, | ||
|
||
off(handler) { | ||
handlers = handlers.filter(h => h !== handler); | ||
}, | ||
|
||
get() { | ||
return value; | ||
}, | ||
|
||
set(newValue, changedBits) { | ||
value = newValue; | ||
handlers.forEach(handler => handler(value, changedBits)); | ||
} | ||
}; | ||
} | ||
|
||
function onlyChild(children) { | ||
return Array.isArray(children) ? children[0] : children; | ||
} | ||
|
||
export default function createReactContext(defaultValue, calculateChangedBits) { | ||
const contextProp = "__create-react-context-" + getUniqueId() + "__"; | ||
|
||
class Provider extends React.Component { | ||
emitter = createEventEmitter(this.props.value); | ||
|
||
static childContextTypes = { | ||
[contextProp]: PropTypes.object.isRequired | ||
}; | ||
|
||
getChildContext() { | ||
return { | ||
[contextProp]: this.emitter | ||
}; | ||
} | ||
|
||
componentWillReceiveProps(nextProps) { | ||
if (this.props.value !== nextProps.value) { | ||
let oldValue = this.props.value; | ||
let newValue = nextProps.value; | ||
let changedBits; | ||
|
||
if (objectIs(oldValue, newValue)) { | ||
changedBits = 0; // No change | ||
} else { | ||
changedBits = | ||
typeof calculateChangedBits === "function" | ||
? calculateChangedBits(oldValue, newValue) | ||
: MAX_SIGNED_31_BIT_INT; | ||
if (process.env.NODE_ENV !== "production") { | ||
warning( | ||
(changedBits & MAX_SIGNED_31_BIT_INT) === changedBits, | ||
"calculateChangedBits: Expected the return value to be a " + | ||
"31-bit integer. Instead received: " + | ||
changedBits | ||
); | ||
} | ||
|
||
changedBits |= 0; | ||
|
||
if (changedBits !== 0) { | ||
this.emitter.set(nextProps.value, changedBits); | ||
} | ||
} | ||
} | ||
} | ||
|
||
render() { | ||
return this.props.children; | ||
} | ||
} | ||
|
||
class Consumer extends React.Component { | ||
static contextTypes = { | ||
[contextProp]: PropTypes.object | ||
}; | ||
|
||
observedBits; | ||
|
||
state = { | ||
value: this.getValue() | ||
}; | ||
|
||
componentWillReceiveProps(nextProps) { | ||
let { observedBits } = nextProps; | ||
this.observedBits = | ||
observedBits === undefined || observedBits === null | ||
? MAX_SIGNED_31_BIT_INT // Subscribe to all changes by default | ||
: observedBits; | ||
} | ||
|
||
componentDidMount() { | ||
if (this.context[contextProp]) { | ||
this.context[contextProp].on(this.onUpdate); | ||
} | ||
let { observedBits } = this.props; | ||
this.observedBits = | ||
observedBits === undefined || observedBits === null | ||
? MAX_SIGNED_31_BIT_INT // Subscribe to all changes by default | ||
: observedBits; | ||
} | ||
|
||
componentWillUnmount() { | ||
if (this.context[contextProp]) { | ||
this.context[contextProp].off(this.onUpdate); | ||
} | ||
} | ||
|
||
getValue() { | ||
if (this.context[contextProp]) { | ||
return this.context[contextProp].get(); | ||
} else { | ||
return defaultValue; | ||
} | ||
} | ||
|
||
onUpdate = (newValue, changedBits) => { | ||
const observedBits = this.observedBits | 0; | ||
if ((observedBits & changedBits) !== 0) { | ||
this.setState({ value: this.getValue() }); | ||
} | ||
}; | ||
|
||
render() { | ||
return onlyChild(this.props.children)(this.state.value); | ||
} | ||
} | ||
|
||
return { | ||
Provider, | ||
Consumer | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters