ReactElement

key prop

  1. // 尝试通过props获取key的时候,将会报错,不能把key作为prop来使用和看待
  2. function defineKeyPropWarningGetter(props, displayName) {
  3. const warnAboutAccessingKey = function() {
  4. if (__DEV__) {
  5. if (!specialPropKeyWarningShown) {
  6. specialPropKeyWarningShown = true;
  7. console.error(
  8. '%s: `key` is not a prop. Trying to access it will result ' +
  9. 'in `undefined` being returned. If you need to access the same ' +
  10. 'value within the child component, you should pass it as a different ' +
  11. 'prop. (https://reactjs.org/link/special-props)',
  12. displayName,
  13. );
  14. }
  15. }
  16. };
  17. // key prop getter覆盖
  18. warnAboutAccessingKey.isReactWarning = true;
  19. Object.defineProperty(props, 'key', {
  20. get: warnAboutAccessingKey,
  21. configurable: true,
  22. });
  23. }

同理 ref也是

  1. function defineRefPropWarningGetter(props, displayName) {
  2. const warnAboutAccessingRef = function() {
  3. if (__DEV__) {
  4. if (!specialPropRefWarningShown) {
  5. specialPropRefWarningShown = true;
  6. console.error(
  7. '%s: `ref` is not a prop. Trying to access it will result ' +
  8. 'in `undefined` being returned. If you need to access the same ' +
  9. 'value within the child component, you should pass it as a different ' +
  10. 'prop. (https://reactjs.org/link/special-props)',
  11. displayName,
  12. );
  13. }
  14. }
  15. };
  16. warnAboutAccessingRef.isReactWarning = true;
  17. Object.defineProperty(props, 'ref', {
  18. get: warnAboutAccessingRef,
  19. configurable: true,
  20. });
  21. }

jsx方法


  1. export function jsx(type, config, maybeKey) {
  2. let propName;
  3. // Reserved names are extracted
  4. const props = {};
  5. let key = null;
  6. let ref = null;
  7. // maybeKey 备选key
  8. if (maybeKey !== undefined) {
  9. key = '' + maybeKey;
  10. }
  11. // 校验key
  12. if (hasValidKey(config)) {
  13. key = '' + config.key;
  14. }
  15. // ref校验 不能为string
  16. if (hasValidRef(config)) {
  17. ref = config.ref;
  18. }
  19. // 开始处理props
  20. for (propName in config) {
  21. // config自身属性且不是保留字
  22. if (
  23. hasOwnProperty.call(config, propName) &&
  24. !RESERVED_PROPS.hasOwnProperty(propName)
  25. ) {
  26. props[propName] = config[propName];
  27. }
  28. }
  29. // 保留字属性 自身属性 比如标签自己的属性 <a href="">
  30. if (type && type.defaultProps) {
  31. const defaultProps = type.defaultProps;
  32. for (propName in defaultProps) {
  33. if (props[propName] === undefined) {
  34. props[propName] = defaultProps[propName];
  35. }
  36. }
  37. }
  38. return ReactElement(
  39. type,
  40. key,
  41. ref,
  42. undefined,
  43. undefined,
  44. ReactCurrentOwner.current,
  45. props,
  46. );
  47. }

createElement

  1. export function createElement(type, config, children) {
  2. let propName;
  3. // Reserved names are extracted
  4. const props = {};
  5. let key = null;
  6. let ref = null;
  7. let self = null;
  8. let source = null;
  9. ...
  10. const childrenLength = arguments.length - 2;
  11. // createElement(type, config, child)
  12. if (childrenLength === 1) {
  13. props.children = children;
  14. } else if (childrenLength > 1) {
  15. // createElement(type, config, child, child2, child3...)
  16. const childArray = Array(childrenLength);
  17. for (let i = 0; i < childrenLength; i++) {
  18. childArray[i] = arguments[i + 2];
  19. }
  20. if (__DEV__) {
  21. if (Object.freeze) {
  22. Object.freeze(childArray);
  23. }
  24. }
  25. props.children = childArray;
  26. }
  27. // Resolve default props
  28. if (type && type.defaultProps) {
  29. const defaultProps = type.defaultProps;
  30. for (propName in defaultProps) {
  31. if (props[propName] === undefined) {
  32. props[propName] = defaultProps[propName];
  33. }
  34. }
  35. }
  36. if (__DEV__) {
  37. if (key || ref) {
  38. const displayName =
  39. typeof type === 'function'
  40. ? type.displayName || type.name || 'Unknown'
  41. : type;
  42. if (key) {
  43. defineKeyPropWarningGetter(props, displayName);
  44. }
  45. if (ref) {
  46. defineRefPropWarningGetter(props, displayName);
  47. }
  48. }
  49. }
  50. return ReactElement(
  51. type,
  52. key,
  53. ref,
  54. self,
  55. source,
  56. ReactCurrentOwner.current,
  57. props,
  58. );
  59. }

ReactContext

ReactLazy

懒加载组件兑现方法

  1. function lazyInitializer<T>(payload: Payload<T>): T {
  2. // 未初始化过的组件
  3. if (payload._status === Uninitialized) {
  4. const ctor = payload._result;
  5. const thenable = ctor(); // 执行 获取promise
  6. // Transition to the next state.
  7. const pending: PendingPayload = (payload: any);
  8. pending._status = Pending; // pending状态
  9. pending._result = thenable;
  10. thenable.then(
  11. moduleObject => {
  12. // 预防其他地方已经执行了获取方法了
  13. if (payload._status === Pending) {
  14. const defaultExport = moduleObject.default;
  15. // Transition to the next state.
  16. const resolved: ResolvedPayload<T> = (payload: any);
  17. // 标记懒加载组件已resolved
  18. resolved._status = Resolved;
  19. // 拿到了组件导出结果
  20. resolved._result = defaultExport;
  21. }
  22. },
  23. error => {
  24. if (payload._status === Pending) {
  25. // Transition to the next state.
  26. const rejected: RejectedPayload = (payload: any);
  27. rejected._status = Rejected;
  28. rejected._result = error;
  29. }
  30. },
  31. );
  32. }
  33. if (payload._status === Resolved) {
  34. return payload._result;
  35. } else {
  36. throw payload._result;
  37. }
  38. }

构造懒加载组件

  1. export function lazy<T>(
  2. ctor: () => Thenable<{default: T, ...}>,
  3. ): LazyComponent<T, Payload<T>> {
  4. const payload: Payload<T> = {
  5. _status: -1, // 未初始化状态
  6. _result: ctor, // 获取方法 一般是构造promise的方法
  7. };
  8. const lazyType: LazyComponent<T, Payload<T>> = {
  9. $$typeof: REACT_LAZY_TYPE,
  10. _payload: payload,
  11. _init: lazyInitializer,
  12. };
  13. return lazyType;
  14. }

ReactForwardRef

forwardRef

  1. /**
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. import {REACT_FORWARD_REF_TYPE, REACT_MEMO_TYPE} from 'shared/ReactSymbols';
  8. export function forwardRef<Props, ElementType: React$ElementType>(
  9. render: (props: Props, ref: React$Ref<ElementType>) => React$Node,
  10. ) {
  11. if (__DEV__) {
  12. if (render != null && render.$$typeof === REACT_MEMO_TYPE) {
  13. console.error(
  14. 'forwardRef requires a render function but received a `memo` ' +
  15. 'component. Instead of forwardRef(memo(...)), use ' +
  16. 'memo(forwardRef(...)).',
  17. );
  18. } else if (typeof render !== 'function') {
  19. console.error(
  20. 'forwardRef requires a render function but was given %s.',
  21. render === null ? 'null' : typeof render,
  22. );
  23. } else {
  24. if (render.length !== 0 && render.length !== 2) {
  25. console.error(
  26. 'forwardRef render functions accept exactly two parameters: props and ref. %s',
  27. render.length === 1
  28. ? 'Did you forget to use the ref parameter?'
  29. : 'Any additional parameter will be undefined.',
  30. );
  31. }
  32. }
  33. if (render != null) {
  34. if (render.defaultProps != null || render.propTypes != null) {
  35. console.error(
  36. 'forwardRef render functions do not support propTypes or defaultProps. ' +
  37. 'Did you accidentally pass a React component?',
  38. );
  39. }
  40. }
  41. }
  42. const elementType = {
  43. $$typeof: REACT_FORWARD_REF_TYPE,
  44. render,
  45. };
  46. if (__DEV__) {
  47. let ownName;
  48. Object.defineProperty(elementType, 'displayName', {
  49. enumerable: false,
  50. configurable: true,
  51. get: function() {
  52. return ownName;
  53. },
  54. set: function(name) {
  55. ownName = name;
  56. if (render.displayName == null) {
  57. render.displayName = name;
  58. }
  59. },
  60. });
  61. }
  62. return elementType;
  63. }

ReactMemo

memo

纯组件 只根据props,context等引发更新或者通过compare提供更新依据

  1. export function memo<Props>(
  2. type: React$ElementType,
  3. compare?: (oldProps: Props, newProps: Props) => boolean,
  4. ) {
  5. const elementType = {
  6. $$typeof: REACT_MEMO_TYPE,
  7. type,
  8. compare: compare === undefined ? null : compare,
  9. };
  10. return elementType;
  11. }

ReactHooks

  1. function resolveDispatcher() {
  2. // 也就是引用current做事情
  3. const dispatcher = ReactCurrentDispatcher.current;
  4. return ((dispatcher: any): Dispatcher);
  5. }
  6. export function useContext<T>(
  7. Context: ReactContext<T>,
  8. unstable_observedBits: number | boolean | void,
  9. ): T {
  10. const dispatcher = resolveDispatcher();
  11. if ((Context: any)._context !== undefined) {
  12. const realContext = (Context: any)._context;
  13. }
  14. }
  15. return dispatcher.useContext(Context, unstable_observedBits);
  16. }
  17. export function useState<S>(
  18. initialState: (() => S) | S,
  19. ): [S, Dispatch<BasicStateAction<S>>] {
  20. const dispatcher = resolveDispatcher();
  21. return dispatcher.useState(initialState);
  22. }
  23. export function useReducer<S, I, A>(
  24. reducer: (S, A) => S,
  25. initialArg: I,
  26. init?: I => S,
  27. ): [S, Dispatch<A>] {
  28. const dispatcher = resolveDispatcher();
  29. return dispatcher.useReducer(reducer, initialArg, init);
  30. }
  31. export function useRef<T>(initialValue: T): {|current: T|} {
  32. const dispatcher = resolveDispatcher();
  33. return dispatcher.useRef(initialValue);
  34. }
  35. export function useEffect(
  36. create: () => (() => void) | void,
  37. deps: Array<mixed> | void | null,
  38. ): void {
  39. const dispatcher = resolveDispatcher();
  40. return dispatcher.useEffect(create, deps);
  41. }
  42. export function useLayoutEffect(
  43. create: () => (() => void) | void,
  44. deps: Array<mixed> | void | null,
  45. ): void {
  46. const dispatcher = resolveDispatcher();
  47. return dispatcher.useLayoutEffect(create, deps);
  48. }
  49. export function useCallback<T>(
  50. callback: T,
  51. deps: Array<mixed> | void | null,
  52. ): T {
  53. const dispatcher = resolveDispatcher();
  54. return dispatcher.useCallback(callback, deps);
  55. }
  56. export function useMemo<T>(
  57. create: () => T,
  58. deps: Array<mixed> | void | null,
  59. ): T {
  60. const dispatcher = resolveDispatcher();
  61. return dispatcher.useMemo(create, deps);
  62. }
  63. export function useImperativeHandle<T>(
  64. ref: {|current: T | null|} | ((inst: T | null) => mixed) | null | void,
  65. create: () => T,
  66. deps: Array<mixed> | void | null,
  67. ): void {
  68. const dispatcher = resolveDispatcher();
  69. return dispatcher.useImperativeHandle(ref, create, deps);
  70. }
  71. export function useDebugValue<T>(
  72. value: T,
  73. formatterFn: ?(value: T) => mixed,
  74. ): void {
  75. if (__DEV__) {
  76. const dispatcher = resolveDispatcher();
  77. return dispatcher.useDebugValue(value, formatterFn);
  78. }
  79. }
  80. export const emptyObject = {};
  81. export function useTransition(): [(() => void) => void, boolean] {
  82. const dispatcher = resolveDispatcher();
  83. return dispatcher.useTransition();
  84. }
  85. export function useDeferredValue<T>(value: T): T {
  86. const dispatcher = resolveDispatcher();
  87. return dispatcher.useDeferredValue(value);
  88. }
  89. export function useOpaqueIdentifier(): OpaqueIDType | void {
  90. const dispatcher = resolveDispatcher();
  91. return dispatcher.useOpaqueIdentifier();
  92. }
  93. export function useMutableSource<Source, Snapshot>(
  94. source: MutableSource<Source>,
  95. getSnapshot: MutableSourceGetSnapshotFn<Source, Snapshot>,
  96. subscribe: MutableSourceSubscribeFn<Source, Snapshot>,
  97. ): Snapshot {
  98. const dispatcher = resolveDispatcher();
  99. return dispatcher.useMutableSource(source, getSnapshot, subscribe);
  100. }
  101. export function useCacheRefresh(): <T>(?() => T, ?T) => void {
  102. const dispatcher = resolveDispatcher();
  103. // $FlowFixMe This is unstable, thus optional
  104. return dispatcher.useCacheRefresh();
  105. }