01. React.forwardRef < P:props , T:ref >

一. interface React.ForwardRefExoticComponent

  1. interface ExoticComponent<P = {}> {
  2. /**
  3. * **NOTE**: Exotic components are not callable.
  4. */
  5. (props: P): (ReactElement|null);
  6. readonly $$typeof: symbol;
  7. }
  8. interface NamedExoticComponent<P = {}> extends ExoticComponent<P> {
  9. displayName?: string;
  10. }
  11. interface ForwardRefExoticComponent<P> extends NamedExoticComponent<P> {
  12. defaultProps?: Partial<P>;
  13. propTypes?: WeakValidationMap<P>;
  14. }
  15. function forwardRef<T, P = {}>(render: ForwardRefRenderFunction<T, P>):ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>>;
  16. // render 参数
  17. interface ForwardRefRenderFunction<T, P = {}> {
  18. /**
  19. * PropsWithChildren<P>
  20. * ref: ForwardedRef<T>
  21. * Function (a: any, value: T): Array<T>; InternalButton === render
  22. */
  23. (props: PropsWithChildren<P>, ref: ForwardedRef<T>): ReactElement | null;
  24. displayName?: string;
  25. // explicit rejected with `never` required due to
  26. // https://github.com/microsoft/TypeScript/issues/36826
  27. /**
  28. * defaultProps are not supported on render functions
  29. */
  30. defaultProps?: never;
  31. /**
  32. * propTypes are not supported on render functions
  33. */
  34. propTypes?: never;
  35. }
  36. // ======== return ======= //
  37. interface ForwardRefExoticComponent<P> {
  38. /**
  39. * **NOTE**: Exotic components are not callable.
  40. * React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLElement>>
  41. */
  42. (props: P): (ReactElement|null); // React.RefAttributes<HTMLElement>
  43. readonly $$typeof: symbol;
  44. displayName?: string;
  45. defaultProps?: Partial<P>;
  46. propTypes?: WeakValidationMap<P>;
  47. }

02. React.Children

React.Children 提供了用于处理 this.props.children 不透明数据结构的实用方法。

一. React.Children.map

  1. React.Children.map(children, function[(thisArg)])

在 children 里的每个直接子节点上调用一个函数,并将 this 设置为 thisArg。如果 children 是一个数组,它将被遍历并为数组中的每个子节点调用该函数。如果子节点为 null 或是 undefined,则此方法将返回 null 或是 undefined,而不会返回数组。

注意:如果 children 是一个 Fragment 对象,它将被视为单一子节点的情况处理,而不会被遍历。

二. React.Children.forEach

React.Children.map() 类似,但它不会返回一个数组。

  1. React.Children.forEach(children, function[(thisArg)])

三. React.Children.count

返回 children 中的组件总数量,等同于通过 map 或 forEach 调用回调函数的次数。

  1. React.Children.count(children)

四. React.Children.only

验证 children 是否只有一个子节点(一个 React 元素),如果有则返回它,否则此方法会抛出错误。

  1. React.Children.only(children)

React.Children.only() 不接受 React.Children.map() 的返回值,因为它是一个数组而并不是 React 元素。

五. React.Children.toArray

将 children 这个复杂的数据结构以数组的方式扁平展开并返回,并为每个子节点分配一个 key。当你想要在渲染函数中操作子节点的集合时,它会非常实用,特别是当你想要在向下传递 this.props.children 之前对内容重新排序或获取子集时。

  1. React.Children.toArray(children)

React.Children.toArray() 在拉平展开子节点列表时,更改 key 值以保留嵌套数组的语义。也就是说,toArray 会为返回数组中的每个 key 添加前缀,以使得每个元素 key 的范围都限定在此函数入参数组的对象内

03. React.Fragment

React.Fragment 组件能够在不额外创建 DOM 元素的情况下,让 render() 方法中返回多个元素。

  1. render() {
  2. return (
  3. <React.Fragment>
  4. Some text.
  5. <h2>A heading</h2>
  6. </React.Fragment>
  7. );
  8. }

你也可以使用其简写语法 <></>。欲了解更多相关信息,请参阅 React v16.2.0: Fragments 支持改进

04.cloneElement()

以 element 元素为样板克隆并返回新的 React 元素。返回元素的 props 是将新的 props 与原始元素的 props 浅层合并后的结果。新的子元素将取代现有的子元素,而来自原始元素的 key 和 ref 将被保留

  1. React.cloneElement(
  2. element,
  3. [props],
  4. [...children]
  5. )
  6. // ======> 等同于//
  7. <element.type {...element.props} {...props}>{children}</element.type>

但是,这也保留了组件的 ref。这意味着当通过 ref 获取子节点时,你将不会意外地从你祖先节点上窃取它。相同的 ref 将添加到克隆后的新元素中。
引入此 API 是为了替换已弃用的 React.addons.cloneWithProps()。


05. React.FunctionComponent (React.F C)

FunctionComponent 既可以当作函数调用,同时又能定义 defaultProps displayName 等固定属性。

  1. interface FunctionComponent<P = {}> {
  2. (props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
  3. propTypes?: WeakValidationMap<P>;
  4. contextTypes?: ValidationMap<any>;
  5. defaultProps?: Partial<P>;
  6. displayName?: string;
  7. }
  8. // props?.children = null
  9. type PropsWithChildren<P> = P & { children?: ReactNode };
  10. import React, { FC } from 'react';
  11. /**
  12. * 声明Props类型
  13. */
  14. export interface MyComponentProps {
  15. className?: string;
  16. style?: React.CSSProperties;
  17. }
  18. export const MyComponent: FC<MyComponentProps> = props => {
  19. return <div>hello react</div>;
  20. };
  21. 等同于
  22. export interface MyComponentProps {
  23. className?: string;
  24. style?: React.CSSProperties;
  25. // 手动声明children
  26. children?: React.ReactNode;
  27. }
  28. export function MyComponent(props: MyComponentProps) {
  29. return <div>hello react</div>;
  30. }
  31. // 导出的模式
  32. export default function Foo(props: {}) {
  33. return <div>xxx</div>;
  34. }