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_TYPEUppercase 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. sotypeof Symbol === 'function'.
    • Symbol.for()Reuse symbol value
    • Symbol.iterableObject that points to the default traverser method for that object
    • @@iteratorThe initial values of the property are andArray.prototype.valuesProperty of an object with the same initial value.
    • Array.prototype.valuesArray.prototype[Symbol.iterator]The default implementation of.

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 memomemo(forwardRef(...) )
  • The forwardRef Render Functions accepts two arguments:props and ref
  • Render must be a function that returns a React node
  • Does not supportpropTypes 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.