Files
react/packages/shared/ReactTypes.js
Andrew Clark 2b509e2c8c [Experimental] API for reading context from within any render phase function (#13139)
* Store list of contexts on the fiber

Currently, context can only be read by a special type of component,
ContextConsumer. We want to add support to all fibers, including
classes and functional components.

Each fiber may read from one or more contexts. To enable quick, mono-
morphic access of this list, we'll store them on a fiber property.

* Context.unstable_read

unstable_read can be called anywhere within the render phase. That
includes the render method, getDerivedStateFromProps, constructors,
functional components, and context consumer render props.

If it's called outside the render phase, an error is thrown.

* Remove vestigial context cursor

Wasn't being used.

* Split fiber.expirationTime into two separate fields

Currently, the `expirationTime` field represents the pending work of
both the fiber itself — including new props, state, and context — and of
any updates in that fiber's subtree.

This commit adds a second field called `childExpirationTime`. Now
`expirationTime` only represents the pending work of the fiber itself.
The subtree's pending work is represented by `childExpirationTime`.

The biggest advantage is it requires fewer checks to bailout on already
finished work. For most types of work, if the `expirationTime` does not
match the render expiration time, we can bailout immediately without
any further checks. This won't work for fibers that have
`shouldComponentUpdate` semantics (class components), for which we still
need to check for props and state changes explicitly.

* Performance nits

Optimize `readContext` for most common case
2018-07-20 16:49:06 -07:00

109 lines
2.2 KiB
JavaScript

/**
* Copyright (c) 2014-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
export type ReactNode =
| React$Element<any>
| ReactCall<any>
| ReactReturn<any>
| ReactPortal
| ReactText
| ReactFragment
| ReactProvider<any>
| ReactConsumer<any>;
export type ReactFragment = ReactEmpty | Iterable<React$Node>;
export type ReactNodeList = ReactEmpty | React$Node;
export type ReactText = string | number;
export type ReactEmpty = null | void | boolean;
export type ReactCall<V> = {
$$typeof: Symbol | number,
type: Symbol | number,
key: null | string,
ref: null,
props: {
props: any,
// This should be a more specific CallHandler
handler: (props: any, returns: Array<V>) => ReactNodeList,
children?: ReactNodeList,
},
};
export type ReactReturn<V> = {
$$typeof: Symbol | number,
type: Symbol | number,
key: null,
ref: null,
props: {
value: V,
},
};
export type ReactProvider<T> = {
$$typeof: Symbol | number,
type: ReactProviderType<T>,
key: null | string,
ref: null,
props: {
value: T,
children?: ReactNodeList,
},
};
export type ReactProviderType<T> = {
$$typeof: Symbol | number,
_context: ReactContext<T>,
};
export type ReactConsumer<T> = {
$$typeof: Symbol | number,
type: ReactContext<T>,
key: null | string,
ref: null,
props: {
children: (value: T) => ReactNodeList,
unstable_observedBits?: number,
},
};
export type ReactContext<T> = {
$$typeof: Symbol | number,
Consumer: ReactContext<T>,
Provider: ReactProviderType<T>,
unstable_read: () => T,
_calculateChangedBits: ((a: T, b: T) => number) | null,
_defaultValue: T,
_currentValue: T,
_currentValue2: T,
_changedBits: number,
_changedBits2: number,
// DEV only
_currentRenderer?: Object | null,
_currentRenderer2?: Object | null,
};
export type ReactPortal = {
$$typeof: Symbol | number,
key: null | string,
containerInfo: any,
children: ReactNodeList,
// TODO: figure out the API for cross-renderer implementation.
implementation: any,
};
export type RefObject = {|
current: any,
|};