+
Skip to content

V18 2 0 with memory fixes #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
89 changes: 37 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,75 +1,60 @@
# [React](https://reactjs.org/) · [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/facebook/react/blob/main/LICENSE) [![npm version](https://img.shields.io/npm/v/react.svg?style=flat)](https://www.npmjs.com/package/react) [![CircleCI Status](https://circleci.com/gh/facebook/react.svg?style=shield&circle-token=:circle-token)](https://circleci.com/gh/facebook/react) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://reactjs.org/docs/how-to-contribute.html#your-first-pull-request)
# `react-dom`

React is a JavaScript library for building user interfaces.

* **Declarative:** React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. Declarative views make your code more predictable, simpler to understand, and easier to debug.
* **Component-Based:** Build encapsulated components that manage their state, then compose them to make complex UIs. Since component logic is written in JavaScript instead of templates, you can easily pass rich data through your app and keep the state out of the DOM.
* **Learn Once, Write Anywhere:** We don't make assumptions about the rest of your technology stack, so you can develop new features in React without rewriting existing code. React can also render on the server using Node and power mobile apps using [React Native](https://reactnative.dev/).

[Learn how to use React in your project](https://reactjs.org/docs/getting-started.html).
This package serves as the entry point to the DOM and server renderers for React. It is intended to be paired with the generic React package, which is shipped as `react` to npm.

## Installation

React has been designed for gradual adoption from the start, and **you can use as little or as much React as you need**:

* Use [Online Playgrounds](https://reactjs.org/docs/getting-started.html#online-playgrounds) to get a taste of React.
* [Add React to a Website](https://reactjs.org/docs/add-react-to-a-website.html) as a `<script>` tag in one minute.
* [Create a New React App](https://reactjs.org/docs/create-a-new-react-app.html) if you're looking for a powerful JavaScript toolchain.

You can use React as a `<script>` tag from a [CDN](https://reactjs.org/docs/cdn-links.html), or as a `react` package on [npm](https://www.npmjs.com/package/react).

## Documentation

You can find the React documentation [on the website](https://reactjs.org/).

Check out the [Getting Started](https://reactjs.org/docs/getting-started.html) page for a quick overview.

The documentation is divided into several sections:

* [Tutorial](https://reactjs.org/tutorial/tutorial.html)
* [Main Concepts](https://reactjs.org/docs/hello-world.html)
* [Advanced Guides](https://reactjs.org/docs/jsx-in-depth.html)
* [API Reference](https://reactjs.org/docs/react-api.html)
* [Where to Get Support](https://reactjs.org/community/support.html)
* [Contributing Guide](https://reactjs.org/docs/how-to-contribute.html)

You can improve it by sending pull requests to [this repository](https://github.com/reactjs/reactjs.org).
```sh
npm install react react-dom
```

## Examples
## Usage

We have several examples [on the website](https://reactjs.org/). Here is the first one to get you started:
### In the browser

```jsx
```js
import { createRoot } from 'react-dom/client';

function HelloMessage({ name }) {
return <div>Hello {name}</div>;
function App() {
return <div>Hello World</div>;
}

const root = createRoot(document.getElementById('container'));
root.render(<HelloMessage name="Taylor" />);
const root = createRoot(document.getElementById('root'));
root.render(<App />);
```

This example will render "Hello Taylor" into a container on the page.

You'll notice that we used an HTML-like syntax; [we call it JSX](https://reactjs.org/docs/introducing-jsx.html). JSX is not required to use React, but it makes code more readable and writing it feels like writing HTML. If you're using React as a `<script>` tag, read [this section](https://reactjs.org/docs/add-react-to-a-website.html#optional-try-react-with-jsx) on integrating JSX; otherwise, the [recommended JavaScript toolchains](https://reactjs.org/docs/create-a-new-react-app.html) handle it automatically.
### On the server

## Contributing
```js
import { renderToPipeableStream } from 'react-dom/server';

The main purpose of this repository is to continue evolving React core, making it faster and easier to use. Development of React happens in the open on GitHub, and we are grateful to the community for contributing bugfixes and improvements. Read below to learn how you can take part in improving React.
function App() {
return <div>Hello World</div>;
}

### [Code of Conduct](https://code.fb.com/codeofconduct)
function handleRequest(res) {
// ... in your server handler ...
const stream = renderToPipeableStream(<App />, {
onShellReady() {
res.statusCode = 200;
res.setHeader('Content-type', 'text/html');
stream.pipe(res);
},
// ...
});
}
```

Facebook has adopted a Code of Conduct that we expect project participants to adhere to. Please read [the full text](https://code.fb.com/codeofconduct) so that you can understand what actions will and will not be tolerated.
## API

### [Contributing Guide](https://reactjs.org/docs/how-to-contribute.html)
### `react-dom`

Read our [contributing guide](https://reactjs.org/docs/how-to-contribute.html) to learn about our development process, how to propose bugfixes and improvements, and how to build and test your changes to React.
See https://reactjs.org/docs/react-dom.html

### Good First Issues
### `react-dom/client`

To help you get your feet wet and get you familiar with our contribution process, we have a list of [good first issues](https://github.com/facebook/react/labels/good%20first%20issue) that contain bugs that have a relatively limited scope. This is a great place to get started.
See https://reactjs.org/docs/react-dom-client.html

### License
### `react-dom/server`

React is [MIT licensed](./LICENSE).
See https://reactjs.org/docs/react-dom-server.html
30 changes: 15 additions & 15 deletions ReactVersions.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,28 +25,28 @@ const ReactVersion = '18.2.0';
const nextChannelLabel = 'next';

const stablePackages = {
'eslint-plugin-react-hooks': '4.6.0',
'jest-react': '0.14.0',
react: ReactVersion,
'react-art': ReactVersion,
// 'eslint-plugin-react-hooks': '4.6.0',
// 'jest-react': '0.14.0',
// react: ReactVersion,
// 'react-art': ReactVersion,
'react-dom': ReactVersion,
'react-is': ReactVersion,
'react-reconciler': '0.29.0',
'react-refresh': '0.14.0',
'react-test-renderer': ReactVersion,
'use-subscription': '1.8.0',
'use-sync-external-store': '1.2.0',
scheduler: '0.23.0',
// 'react-is': ReactVersion,
// 'react-reconciler': '0.29.0',
// 'react-refresh': '0.14.0',
// 'react-test-renderer': ReactVersion,
// 'use-subscription': '1.8.0',
// 'use-sync-external-store': '1.2.0',
// scheduler: '0.23.0',
};

// These packages do not exist in the @next or @latest channel, only
// @experimental. We don't use semver, just the commit sha, so this is just a
// list of package names instead of a map.
const experimentalPackages = [
'react-fetch',
'react-fs',
'react-pg',
'react-server-dom-webpack',
// 'react-fetch',
// 'react-fs',
// 'react-pg',
// 'react-server-dom-webpack',
];

module.exports = {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,4 @@
"resolutions": {
"react-is": "npm:react-is"
}
}
}
4 changes: 4 additions & 0 deletions packages/react-art/src/ReactARTHostConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -451,3 +451,7 @@ export function preparePortalMount(portalInstance: any): void {
export function detachDeletedInstance(node: Instance): void {
// noop
}

export function detatchFiberStateNode(fiber: Fiber): void {
// noop
}
5 changes: 3 additions & 2 deletions packages/react-dom/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-dom",
"version": "18.1.0",
"version": "18.2.0",
"description": "React package for working with the DOM.",
"main": "index.js",
"repository": {
Expand All @@ -21,11 +21,12 @@
"scheduler": "^0.22.0"
},
"peerDependencies": {
"react": "^18.1.0"
"react": "^18.2.0"
},
"files": [
"LICENSE",
"README.md",
"build-info.json",
"index.js",
"client.js",
"profiling.js",
Expand Down
24 changes: 24 additions & 0 deletions packages/react-dom/src/client/ReactDOMComponentTree.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,35 @@ export function detachDeletedInstance(node: Instance): void {
// these fields are relevant.
delete (node: any)[internalInstanceKey];
delete (node: any)[internalPropsKey];
delete (node: any)[internalContainerInstanceKey];
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was something we also cleared out in the previous v17 fix, however its not needed imo. This is only set for the container root node (which I think means the root of react's tree). since v17, you can have multiple roots so react can run multiple versions, but I think we only have one root.

delete (node: any)[internalEventHandlersKey];
delete (node: any)[internalEventHandlerListenersKey];
delete (node: any)[internalEventHandlesSetKey];
}

function _tagIsDetachable(tag: number): boolean {
if (tag == null) {
return false;
}
return tag === HostComponent || tag === HostText;
}

export function detatchFiberStateNode(
fiberToDetach: Fiber,
) {
if (_tagIsDetachable(fiberToDetach.tag)) {
const hostInstance: Instance = fiberToDetach.stateNode;
if (hostInstance !== null) {
detachDeletedInstance(hostInstance);
}
}
fiberToDetach.stateNode = null;

if (fiberToDetach.alternate !== null) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my understanding, fiber.alternate is the Fiber that stores future/new work. Not all fibers will have future work, but if we're unmounting a fiber, we should be sure to cleanup the "future" state too.

detatchFiberStateNode(fiberToDetach.alternate)
}
}

export function precacheFiberNode(
hostInst: Fiber,
node: Instance | TextInstance | SuspenseInstance | ReactScopeInstance,
Expand Down
2 changes: 1 addition & 1 deletion packages/react-dom/src/client/ReactDOMHostConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
getInstanceFromNode as getInstanceFromNodeDOMTree,
isContainerMarkedAsRoot,
} from './ReactDOMComponentTree';
export {detachDeletedInstance} from './ReactDOMComponentTree';
export {detachDeletedInstance, detatchFiberStateNode} from './ReactDOMComponentTree';
import {hasRole} from './DOMAccessibilityRoles';
import {
createElement,
Expand Down
4 changes: 4 additions & 0 deletions packages/react-native-renderer/src/ReactFabricHostConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -612,3 +612,7 @@ export function preparePortalMount(portalInstance: Instance): void {
export function detachDeletedInstance(node: Instance): void {
// noop
}

export function detatchFiberStateNode(fiber: Fiber): void {
// noop
}
4 changes: 4 additions & 0 deletions packages/react-native-renderer/src/ReactNativeHostConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -513,3 +513,7 @@ export function preparePortalMount(portalInstance: Instance): void {
export function detachDeletedInstance(node: Instance): void {
// noop
}

export function detatchFiberStateNode(fiber: Fiber): void {
// noop
}
4 changes: 4 additions & 0 deletions packages/react-noop-renderer/src/createReactNoop.js
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,10 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {

detachDeletedInstance() {},

detatchFiberStateNode() {
// no-op
},

logRecoverableError() {
// no-op
},
Expand Down
36 changes: 16 additions & 20 deletions packages/react-reconciler/src/ReactFiberCommitWork.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ import {
CacheComponent,
TracingMarkerComponent,
} from './ReactWorkTags';
import {detachDeletedInstance} from './ReactFiberHostConfig';
import {
NoFlags,
ContentReset,
Expand Down Expand Up @@ -130,6 +129,7 @@ import {
prepareScopeUpdate,
prepareForCommit,
beforeActiveInstanceBlur,
detatchFiberStateNode,
} from './ReactFiberHostConfig';
import {
captureCommitPhaseError,
Expand Down Expand Up @@ -1335,6 +1335,12 @@ function detachFiberMutation(fiber: Fiber) {
}

function detachFiberAfterEffects(fiber: Fiber) {
// The `stateNode` is cyclical because on host nodes it points to the host
// tree, which has its own pointers to children, parents, and siblings.
// The other host nodes also point back to fibers, so we should detach that
// one, too.
detatchFiberStateNode(fiber);

const alternate = fiber.alternate;
if (alternate !== null) {
fiber.alternate = null;
Expand Down Expand Up @@ -1369,18 +1375,6 @@ function detachFiberAfterEffects(fiber: Fiber) {
fiber.deletions = null;
fiber.sibling = null;

// The `stateNode` is cyclical because on host nodes it points to the host
// tree, which has its own pointers to children, parents, and siblings.
// The other host nodes also point back to fibers, so we should detach that
// one, too.
if (fiber.tag === HostComponent) {
const hostInstance: Instance = fiber.stateNode;
if (hostInstance !== null) {
detachDeletedInstance(hostInstance);
}
}
fiber.stateNode = null;
Comment on lines -1376 to -1382
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

abstracting this to detatchFiberStateNode so we can try to run this in a couple of different places.


// I'm intentionally not clearing the `return` field in this level. We
// already disconnect the `return` pointer at the root of the deleted
// subtree (in `detachFiberMutation`). Besides, `return` by itself is not
Expand Down Expand Up @@ -1736,7 +1730,7 @@ function commitDeletionEffectsOnFiber(
deletedFiber,
);
}
return;
break;
}
case DehydratedFragment: {
if (enableSuspenseCallback) {
Expand Down Expand Up @@ -1767,7 +1761,7 @@ function commitDeletionEffectsOnFiber(
}
}
}
return;
break;
}
case HostPortal: {
if (supportsMutation) {
Expand All @@ -1792,7 +1786,7 @@ function commitDeletionEffectsOnFiber(
deletedFiber,
);
}
return;
break;
}
case FunctionComponent:
case ForwardRef:
Expand Down Expand Up @@ -1856,7 +1850,7 @@ function commitDeletionEffectsOnFiber(
nearestMountedAncestor,
deletedFiber,
);
return;
break;
}
case ClassComponent: {
if (!offscreenSubtreeWasHidden) {
Expand All @@ -1875,7 +1869,7 @@ function commitDeletionEffectsOnFiber(
nearestMountedAncestor,
deletedFiber,
);
return;
break;
}
case ScopeComponent: {
if (enableScopeAPI) {
Expand All @@ -1886,7 +1880,7 @@ function commitDeletionEffectsOnFiber(
nearestMountedAncestor,
deletedFiber,
);
return;
break;
}
case OffscreenComponent: {
if (
Expand Down Expand Up @@ -1927,9 +1921,11 @@ function commitDeletionEffectsOnFiber(
nearestMountedAncestor,
deletedFiber,
);
return;
break;
}
}
// GC any references to this fibers state node.
detatchFiberStateNode(deletedFiber);
}
function commitSuspenseCallback(finishedWork: Fiber) {
// TODO: Move this to passive phase
Expand Down
Loading
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载