Entry file packages/react/SRC/react. Js
Notes for your own use. If you need to browse, please think for yourself. The content is not completed.
shared/ReactVersion.js
Output the current react version
shared/ReactSymbols.js
- React constant names:
REACT_ELEMENT_TYPE
Uppercase name. This approach can also be used as a specification for your own projects. - A prime number is a number that is divisible only by 1 and itself. With JS code to achieve a prime generator
- Symbol
- Although Symbol is a new data type introduced for ES6, values are generated through the Symbol function. so
typeof Symbol === 'function'
. Symbol.for()
Reuse symbol valueSymbol.iterable
Object that points to the default traverser method for that object@@iterator
The initial values of the property are andArray.prototype.values
Property of an object with the same initial value.Array.prototype.values
是Array.prototype[Symbol.iterator]
The default implementation of.
- Although Symbol is a new data type introduced for ES6, values are generated through the Symbol function. so
ReactBaseClasses.js
The class basis
class Point{}
typeof Point === 'object'
Copy the code
Class declares that all methods are defined on Prototype
The object.keys () method returns an array of a given Object’s own enumerable properties in the same order as the property names would be returned if the Object were iterated through normally. Es6 class internally declared properties are not enumerable
The attributes of an instance are defined on the stereotype (class) unless they are explicitly defined on themselves (that is, on this object). React does the following differ:
class Test extends Component {
state = { a: '1'}}class Test1 extends Component {
constructor(props){
super(props)
this.state = {a: '1'}}}Copy the code
Ruan yifeng explained: “The advantage of this new writing method is that all the attributes of the instance object are defined in the head of the class, so it looks neat, and you can see what instance attributes the class has at a glance.” In the actual development process, we can use it at our discretion.
In development, we use __proto__ to get the prototype of the instance, but this property is non-standard. In real development, we can use Object.getProtoTypeof to get the prototype of the Object
Get and set is set within the Object of the attributes of the Descriptor Object Object. GetOwnPropertyDescriptor (o, key)
New. target returns the constructor on which the new command is applied. This property is normally used in constructors to determine whether the constructor was called by the new method. If not, new.target returns undefined
The super keyword, which calls the constructor method of the parent class. Subclasses must call the super method from the constructor method or they will get an error when creating a new instance. This is because the subclass’s this object must be molded by the parent’s constructor to get the same instance attributes and methods as the parent, and then processed to add the subclass’s instance attributes and methods. If you don’t call super, your subclasses don’t get this.
As a super super () function calls, returns the child object instance, equivalent to the Parent. The prototype. The constructor. Call (this), one of this for the child object instance. When called as a super object, in a normal method, the prototype object points to the parent class; In static methods, point to the parent class.
ES6 states that when a method of a parent class is called through super in a subclass normal method, this inside the method refers to the current subclass instance.
Class is the syntactic sugar of the constructor and has both the Prototype and __proto__ attributes, so there are two inheritance chains.
(1) The __proto__ attribute of a subclass, which indicates the constructor’s inheritance, always points to the parent class.
(2) The prototype attribute’s __proto__ attribute, indicating method inheritance, always points to the prototype attribute of the parent class.
Back to the source code
Console can use %s as a placeholder to output subsequent incoming content. This feature can also be used to prompt developers in the underlying code of daily projects.
.console.warn(
'%s(...) is deprecated in plain JavaScript React classes. %s',
info[0],
info[1]); .Copy the code
React Update code react Update code
function Component(props, context, updater) {...this.updater = updater || ReactNoopUpdateQueue;
}
Copy the code
Component.prototype.setState = function(partialState, callback) {...this.updater.enqueueSetState(this, partialState, callback, 'setState');
};
Copy the code
Component.prototype.forceUpdate = function(callback) {
this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
};
Copy the code
The realization of the PureComponent
Es5’s classic inheritance implementation declares a ComponentDummy and assigns a Component stereotype to ComponentDummy
function ComponentDummy() {}
ComponentDummy.prototype = Component.prototype;
Copy the code
Then declare the PureComponent function, which is implemented in the same way as Component
/** * Convenience component with default shallow equality check for sCU. */
function PureComponent(props, context, updater) {
this.props = props;
this.context = context;
// If a component has string refs, we will assign a different object later.
this.refs = emptyObject;
this.updater = updater || ReactNoopUpdateQueue;
}
Copy the code
Point the PureComponent’s Prototype to an instance of ComponentDummy
const pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());
pureComponentPrototype.constructor = PureComponent;
// Avoid an extra prototype jump for these methods.
Object.assign(pureComponentPrototype, Component.prototype);
pureComponentPrototype.isPureReactComponent = true;
Copy the code
Note that there is an optimization point here:
Object.assign(pureComponentPrototype, Component.prototype);
Copy the code
Purecomponent. prototype is assigned a reference to the component. prototype property using the Object.assign method directly. This way you don’t need to go through the prototype chain (__proto__.__proto__) to get methods like setState inside the PureComponent
ReactCreateRef.js
Here you can see the implementation of createRef:
// RefObject is the corresponding type of type
export function createRef() :RefObject {
const refObject = {
current: null};if (__DEV__) {
Object.seal(refObject);
}
return refObject;
}
Copy the code
The object.seal () method closes an Object, a refObject, that passes through Object.seal. The reference remains unchanged, but attributes cannot be added or removed, but current can be assigned
ReactChildren.js
IsArray encapsulates the Array. The hasOwnProperty isArray method encapsulates the Object. The prototype. The hasOwnProperty method can see the react to some and native js do decoupling processing, convenient for the follow-up maintenance
ReactElement.js
The default config
const RESERVED_PROPS = {
key: true.ref: true.__self: true.__source: true};Copy the code
React Special attributes ref and key
Object. GetOwnPropertyDescriptor () method returns the specified Object on a has its own corresponding attribute descriptor. Return the following objects:
{
value, // any
writable, // true/false
configurable, // true/false
enumerable, // true/false
get, // getter function/undefined
set, // setter function/undefined
}
Copy the code
Through defineKeyPropWarningGetter and defineRefPropWarningGetter we can see that the key and the ref property getter accessor function was set up, so we visit these two properties will be undefined.
Safe ways to convert strings:
const toBeString = ' ' + o
Copy the code
function jsx(type, config, maybeKey) {...return ReactElement(
type,
key,
ref,
undefined.undefined,
ReactCurrentOwner.current,
props,
)
}
// self and source are DEV only properties.
const ReactElement = function(type, key, ref, self, source, owner, props) {
const element = {
// This tag allows us to uniquely identify this as a React Element
// Check whether it is a reactElement
$$typeof: REACT_ELEMENT_TYPE,
// Built-in properties that belong on the element
type: type,
key: key,
ref: ref,
props: props,
// Record the component responsible for creating this element.
_owner: owner, }; .return element;
}
/** * Create and return a new ReactElement of the given type. * See https://reactjs.org/docs/react-api.html#createelement */
function createElement(type, config, children){...return ReactElement(
type,
key,
ref,
self,
source,
ReactCurrentOwner.current,
props,
);
}
Copy the code
ReactCurrentOwner.js
The parent component of the current building
const ReactCurrentOwner = {
/ * * *@internal
* @type {ReactComponent}* /
current: (null: null | Fiber),
};
Copy the code
ReactContext.js
How does reactContext work?
function createContext<T> (defaultValue: T) :ReactContext<T> {
const context: ReactContext<T> = {
$$typeof: REACT_CONTEXT_TYPE,
// As a workaround to support multiple concurrent renderers, we categorize
// some renderers as primary and others as secondary. We only expect
// there to be two concurrent renderers at most: React Native (primary) and
// Fabric (secondary); React DOM (primary) and React ART (secondary).
// Secondary renderers store their context values on separate fields.
_currentValue: defaultValue,
_currentValue2: defaultValue,
// Used to track how many concurrent renderers this context currently
// supports within in a single renderer. Such as parallel server rendering.
_threadCount: 0.// These are circular
Provider: (null: any),
Consumer: (null: any),
};
context.Provider = {
$$typeof: REACT_PROVIDER_TYPE,
_context: context, }; . context.Consumer = context;return context
}
Copy the code
ReactLazy.js
// Define promise type constants.function lazyInitializer<T> (payload: Payload<T>) :T {
if (payload._status === Uninitialized) {
const ctor = payload._result;
/ / perform the import ()
const thenable = ctor();
// Change the status to pending
// Transition to the next state.
const pending: PendingPayload = (payload: any);
pending._status = Pending;
pending._result = thenable;
// Execute the then(onFullfilled, onRejected) method
thenable.then(
moduleObject= > {
if (payload._status === Pending) {
const defaultExport = moduleObject.default;
if (__DEV__) {
if (defaultExport === undefined) {
console.error(
'lazy: Expected the result of a dynamic import() call. ' +
'Instead received: %s\n\nYour code should look like: \n ' +
// Break up imports to avoid accidentally parsing them as dependencies.
'const MyComponent = lazy(() => imp' +
"ort('./MyComponent'))", moduleObject, ); }}// Transition to the next state.
constresolved: ResolvedPayload<T> = (payload: any); resolved._status = Resolved; resolved._result = defaultExport; }},error= > {
if (payload._status === Pending) {
// Transition to the next state.
constrejected: RejectedPayload = (payload: any); rejected._status = Rejected; rejected._result = error; }}); }if (payload._status === Resolved) {
return payload._result;
} else {
throwpayload._result; }}function lazyfunction lazy<T> (
ctor: () => Thenable<{default: T, ... } >.) :LazyComponent<T.Payload<T>> {
const payload: Payload<T> = {
// We use these fields to store the result.
_status: -1._result: ctor,
};
const lazyType: LazyComponent<T, Payload<T>> = {
$$typeof: REACT_LAZY_TYPE,
_payload: payload,
// init function that accepts payload as a parameter
_init: lazyInitializer,
};
return lazyType
}
Copy the code
ReactForwardRef.js
React.forwardRef accepts the render function as an argument. React will call this function with props and ref as arguments. This function should return the React node.
export function forwardRef<Props.ElementType: React$ElementType> (
render: (props: Props, ref: React$Ref<ElementType>) => React$Node,
) {
const elementType = {
$$typeof: REACT_FORWARD_REF_TYPE,
render,
};
return elementType;
}
Copy the code
Gets the number of arguments to the function: function.length
- Use memo
memo(forwardRef(...) )
- The forwardRef Render Functions accepts two arguments:
props and ref
- Render must be a function that returns a React node
- Does not support
propTypes or defaultProps
ReactMemo.js
React.memo only checks the props changes. If the function component is wrapped in react. Memo and its implementation has a Hook for useState, useReducer, or useContext, it will still rerender when the context changes.
By default, only shallow comparisons are performed on complex objects. If you want to control the comparison process, pass in your custom comparison function as a second argument.
export function memo<Props> (type: React$ElementType, compare? : (oldProps: Props, newProps: Props) => boolean,) {
const elementType = {
$$typeof: REACT_MEMO_TYPE,
type,
compare: compare === undefined ? null : compare,
};
return elementType;
}
Copy the code
ReactHooks.js
function resolveDispatcher() {
const dispatcher = ReactCurrentDispatcher.current;
if (__DEV__) {
if (dispatcher === null) {
console.error(
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
' one of the following reasons:\n' +
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
'2. You might be breaking the Rules of Hooks\n' +
'3. You might have more than one copy of React in the same app\n' +
'See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.',); }}// Will result in a null access error if accessed outside render phase. We
// intentionally don't throw our own error because this is in a hot path.
// Also helps ensure this is inlined.
return ((dispatcher: any): Dispatcher);
Copy the code
useContext
export function useContext<T> (Context: ReactContext<T>) :T {
constdispatcher = resolveDispatcher(); .return dispatcher.useContext(Context);
}
Copy the code
useState
export function useState<S> (
initialState: (() => S) | S,
) :S.Dispatch<BasicStateAction<S> >]{
const dispatcher = resolveDispatcher();
return dispatcher.useState(initialState);
}
Copy the code
useReducer
An alternative to useState. It receives a Reducer of the form (state, action) => newState and returns the current state and its accompanying dispatch method. (If you’re familiar with Redux, you already know how it works.)
export function useReducer<S.I.A> (reducer: (S, A) => S, initialArg: I, init? : I => S,) :S.Dispatch<A>] {
const dispatcher = resolveDispatcher();
return dispatcher.useReducer(reducer, initialArg, init);
}
Copy the code
React ensures that the identity of the Dispatch function is stable and does not change when the component is re-rendered. This is why it is safe to omit Dispatch from useEffect or useCallback’s dependency list.
useRef
export function useRef<T> (initialValue: T) :{|current: T|} {
const dispatcher = resolveDispatcher();
return dispatcher.useRef(initialValue);
}
Copy the code
useEffect
export function useEffect(
create: () => (() => void) | void,
deps: Array<mixed> | void | null.) :void {
const dispatcher = resolveDispatcher();
return dispatcher.useEffect(create, deps);
}
Copy the code
useLayoutEffect
Its function signature is the same as useEffect, but it calls Effect synchronously after all DOM changes. You can use it to read DOM layouts and trigger rerenders synchronously. The update schedule inside useLayoutEffect is refreshed synchronously before the browser performs the drawing.
Use standard Useeffects whenever possible to avoid blocking visual updates.
- Execute synchronously and block rendering
- Execute before render
export function useLayoutEffect(
create: () => (() => void) | void,
deps: Array<mixed> | void | null.) :void {
const dispatcher = resolveDispatcher();
return dispatcher.useLayoutEffect(create, deps);
}
Copy the code
useCallback
export function useCallback<T> (
callback: T,
deps: Array<mixed> | void | null.) :T {
const dispatcher = resolveDispatcher();
return dispatcher.useCallback(callback, deps);
}
Copy the code
useMemo
export function useMemo<T> (
create: () => T,
deps: Array<mixed> | void | null.) :T {
const dispatcher = resolveDispatcher();
return dispatcher.useMemo(create, deps);
}
Copy the code
useImperativeHandle
UseImperativeHandle allows you to customize the instance value exposed to the parent component when using a ref. In most cases, imperative code like ref should be avoided. UseImperativeHandle should be used together with the forwardRef
export function useImperativeHandle<T> (
ref: {|current: T | null|} | ((inst: T | null) => mixed) | null | void,
create: () => T,
deps: Array<mixed> | void | null.) :void {
const dispatcher = resolveDispatcher();
return dispatcher.useImperativeHandle(ref, create, deps);
}
Copy the code
useDebugValue
UseDebugValue can be used to display tags for custom hooks in the React developer tool.
export function useDebugValue<T> (value: T, formatterFn: ? (value: T) => mixed,) :void {
if (__DEV__) {
const dispatcher = resolveDispatcher();
returndispatcher.useDebugValue(value, formatterFn); }}Copy the code
useTransition
export function useTransition() :boolean, (() = >void) = >void] {
const dispatcher = resolveDispatcher();
return dispatcher.useTransition();
}
Copy the code
useDeferredValue
export function useDeferredValue<T> (value: T) :T {
const dispatcher = resolveDispatcher();
return dispatcher.useDeferredValue(value);
}
Copy the code
ReactCurrentDispatcher.js
const ReactCurrentDispatcher = {
/ * * *@internal
* @type {ReactComponent}* /
current: (null: null | Dispatcher),
};
Copy the code
ReactElementValidator.js
Development environment __DEV__ some validation methods
Other knowledge points
In CSS, you can use the display: contents property if you don’t want nodes to be part of the layout.