Skip to content

Commit 02068ca

Browse files
more React 18 [wip]
NOTES: Context’s calculateChangedBits was removed or altered… not sure which.
1 parent 582f969 commit 02068ca

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+5259
-4925
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,14 @@ __New Features__
120120
import 'some_widget.dart'; // Where your component is defined
121121
122122
main() {
123+
final root = react_dom.createRoot(querySelector('#idOfSomeNodeInTheDom'));
123124
final renderedWidget = SomeWidget({
124125
// put some props here
125126
}, [
126127
// put some children here!
127128
]);
128129
129-
react_dom.render(renderedWidget, querySelector('#idOfSomeNodeInTheDom'));
130+
root.render(renderedWidget);
130131
}
131132
```
132133

README.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Dart wrapper for [React JS](https://reactjs.org/)
22

33
[![Pub](https://img.shields.io/pub/v/react.svg)](https://pub.dev/packages/react)
4-
![ReactJS v17.0.1](https://img.shields.io/badge/React_JS-v17.0.1-green.svg)
4+
![ReactJS v18.0.0](https://img.shields.io/badge/React_JS-v18.0.0-green.svg)
55
[![Dart CI](https://github.com/Workiva/react-dart/workflows/Dart%20CI/badge.svg?branch=master)](https://github.com/Workiva/react-dart/actions?query=workflow%3A%22Dart+CI%22+branch%3Amaster)
66
[![React Dart API Docs](https://img.shields.io/badge/api_docs-react-blue.svg)](https://pub.dev/documentation/react/latest/)
77

@@ -81,7 +81,8 @@ main() {
8181
var component = div({}, "Hello world!");
8282
8383
// Render it into the mount node we created in our .html file.
84-
react_dom.render(component, querySelector('#react_mount_point'));
84+
final root = react_dom.createRoot(querySelector('#react_mount_point'));
85+
root.render(component);
8586
}
8687
```
8788
@@ -141,7 +142,8 @@ var aButton = button({"onClick": (SyntheticMouseEvent event) => print(event)});
141142
import 'cool_widget.dart';
142143
143144
main() {
144-
react_dom.render(CoolWidget({}), querySelector('#react_mount_point'));
145+
final root = react_dom.createRoot(querySelector('#react_mount_point'));
146+
root.render(CoolWidget({}));
145147
}
146148
```
147149
@@ -173,7 +175,8 @@ import 'package:react/react_dom.dart' as react_dom;
173175
import 'cool_widget.dart';
174176
175177
main() {
176-
react_dom.render(CoolWidget({"text": "Something"}), querySelector('#react_mount_point'));
178+
final root = react_dom.createRoot(querySelector('#react_mount_point'));
179+
root.render(CoolWidget({"text": "Something"}));
177180
}
178181
```
179182
@@ -221,13 +224,13 @@ import 'package:react/react_dom.dart' as react_dom;
221224
import 'cool_widget.dart';
222225
223226
void main() {
224-
react_dom.render(
227+
final root = react_dom.createRoot(querySelector('#react_mount_point'));
228+
root.render(
225229
myComponent(
226230
headline: "My custom headline",
227231
text: "My custom text",
228232
counter: 3,
229-
),
230-
querySelector('#react_mount_point')
233+
)
231234
);
232235
}
233236
```
@@ -375,7 +378,7 @@ void main() {
375378
expect(spanNode.text, equals('testing...'));
376379
377380
// Click the button and trigger the onClick event
378-
react_test_utils.Simulate.click(buttonNode);
381+
react_dom.ReactTestUtils.act(buttonNode.click);
379382
380383
// Span text should change to 'success'
381384
expect(spanNode.text, equals('success'));

example/geocodes/geocodes.dart

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// ignore_for_file: deprecated_member_use_from_same_package
21
import 'dart:async';
32
import 'dart:convert';
43
import 'dart:html';
@@ -28,7 +27,7 @@ import 'package:react/react_dom.dart' as react_dom;
2827
/// This is the first custom [Component].
2928
///
3029
/// It is just an HTML `<tr>` element displaying a single API response to the user.
31-
class _GeocodesResultItem extends react.Component {
30+
class _GeocodesResultItem extends react.Component2 {
3231
/// The only function you must implement in the custom component is [render].
3332
///
3433
/// Every [Component] has a map of properties called [Component.props]. It can be specified during creation.
@@ -48,11 +47,11 @@ class _GeocodesResultItem extends react.Component {
4847
/// shortly.
4948
///
5049
/// This is the only correct way to create a [Component]. Do not use the constructor!
51-
var geocodesResultItem = react.registerComponent(() => new _GeocodesResultItem());
50+
var GeocodesResultItem = react.registerComponent2(() => _GeocodesResultItem());
5251

5352
/// In this component we'll build an HTML `<table>` element full of the `<tr>` elements generated by
5453
/// [_GeocodesResultItem]
55-
class _GeocodesResultList extends react.Component {
54+
class _GeocodesResultList extends react.Component2 {
5655
@override
5756
render() {
5857
// Built-in HTML DOM components also have props - which correspond to HTML element attributes.
@@ -83,7 +82,7 @@ class _GeocodesResultList extends react.Component {
8382
// The second argument contains the body of the component (as you have already seen).
8483
//
8584
// It can be a String, a Component or an Iterable.
86-
props['data'].map((item) => geocodesResultItem({
85+
props['data'].map((item) => GeocodesResultItem({
8786
'key': item['formatted_address'],
8887
'lat': item['geometry']['location']['lat'],
8988
'lng': item['geometry']['location']['lng'],
@@ -95,7 +94,7 @@ class _GeocodesResultList extends react.Component {
9594
}
9695
}
9796

98-
var geocodesResultList = react.registerComponent(() => new _GeocodesResultList());
97+
var GeocodesResultList = react.registerComponent2(() => _GeocodesResultList());
9998

10099
/// In this [Component] we'll build a search form.
101100
///
@@ -104,11 +103,11 @@ var geocodesResultList = react.registerComponent(() => new _GeocodesResultList()
104103
/// > The functions can be [Component] parameters _(handy for callbacks)_
105104
///
106105
/// > The DOM [Element]s can be accessed using `ref`s.
107-
class _GeocodesForm extends react.Component {
108-
var searchInputInstance;
106+
class _GeocodesForm extends react.Component2 {
107+
final searchInputRef = react.createRef<InputElement>();
109108

110109
@override
111-
getInitialState() => {
110+
get initialState => {
112111
'value': '',
113112
};
114113

@@ -136,7 +135,7 @@ class _GeocodesForm extends react.Component {
136135
'value': state['value'],
137136
'onChange': handleChange,
138137
// Input is referenced to access it's value
139-
'ref': (searchInputInstance) => this.searchInputInstance = searchInputInstance,
138+
'ref': searchInputRef,
140139
}),
141140
react.span({
142141
'key': 'spacer',
@@ -158,7 +157,7 @@ class _GeocodesForm extends react.Component {
158157
/// Handle form submission via `props.onSubmit`
159158
onFormSubmit(react.SyntheticEvent event) {
160159
event.preventDefault();
161-
InputElement inputElement = react_dom.findDOMNode(searchInputInstance);
160+
final inputElement = searchInputRef.current;
162161
// The input's value is accessed.
163162
var address = inputElement.value;
164163
inputElement.value = '';
@@ -167,10 +166,10 @@ class _GeocodesForm extends react.Component {
167166
}
168167
}
169168

170-
var geocodesForm = react.registerComponent(() => new _GeocodesForm());
169+
var GeocodesForm = react.registerComponent2(() => _GeocodesForm());
171170

172171
/// Renders an HTML `<li>` to be used as a child within the [_GeocodesHistoryList].
173-
class _GeocodesHistoryItem extends react.Component {
172+
class _GeocodesHistoryItem extends react.Component2 {
174173
reload(e) {
175174
props['reloader'](props['query']);
176175
}
@@ -189,12 +188,12 @@ class _GeocodesHistoryItem extends react.Component {
189188
}
190189
}
191190

192-
var geocodesHistoryItem = react.registerComponent(() => new _GeocodesHistoryItem());
191+
var GeocodesHistoryItem = react.registerComponent2(() => _GeocodesHistoryItem());
193192

194193
/// Renders the "history list"
195194
///
196195
/// NOTE: It just passes the callback from the parent.
197-
class _GeocodesHistoryList extends react.Component {
196+
class _GeocodesHistoryList extends react.Component2 {
198197
@override
199198
render() {
200199
return react.div({}, [
@@ -203,7 +202,7 @@ class _GeocodesHistoryList extends react.Component {
203202
{
204203
'key': 'list',
205204
},
206-
new List.from(props['data'].keys.map((key) => geocodesHistoryItem({
205+
new List.from(props['data'].keys.map((key) => GeocodesHistoryItem({
207206
'key': key,
208207
'query': props['data'][key]['query'],
209208
'status': props['data'][key]['status'],
@@ -214,7 +213,7 @@ class _GeocodesHistoryList extends react.Component {
214213
}
215214
}
216215

217-
var geocodesHistoryList = react.registerComponent(() => new _GeocodesHistoryList());
216+
var GeocodesHistoryList = react.registerComponent2(() => _GeocodesHistoryList());
218217

219218
/// The root [Component] of our application.
220219
///
@@ -234,9 +233,9 @@ var geocodesHistoryList = react.registerComponent(() => new _GeocodesHistoryList
234233
///
235234
/// When the request is sent, it has `pending` status in the history. This changes to `OK` or `error` when the answer
236235
/// _(or timeout)_ comes. If the new request is sent meanwhile, the old one is cancelled.
237-
class _GeocodesApp extends react.Component {
236+
class _GeocodesApp extends react.Component2 {
238237
@override
239-
getInitialState() => {
238+
get initialState => {
240239
'shown_addresses': [], // Data from last query.
241240
'history': {} // Map of past queries.
242241
};
@@ -304,17 +303,17 @@ class _GeocodesApp extends react.Component {
304303
render() {
305304
return react.div({}, [
306305
react.h1({'key': '1'}, 'Geocode resolver'),
307-
geocodesResultList({
306+
GeocodesResultList({
308307
'key': '2',
309308
// The state values are passed to the children as the properties.
310309
'data': state['shown_addresses']
311310
}),
312-
geocodesForm({
311+
GeocodesForm({
313312
'key': '3',
314313
// `newQuery` is the final callback of the button click.
315314
'submitter': newQuery
316315
}),
317-
geocodesHistoryList({
316+
GeocodesHistoryList({
318317
'key': '4',
319318
'data': state['history'],
320319
// `newQuery` is the final callback of the button click.
@@ -324,11 +323,12 @@ class _GeocodesApp extends react.Component {
324323
}
325324
}
326325

327-
var geocodesApp = react.registerComponent(() => new _GeocodesApp());
326+
var GeocodesApp = react.registerComponent2(() => _GeocodesApp());
328327

329328
/// And finally, a few magic commands to wire it all up!
330329
///
331330
/// Select the root of the app and the place in the DOM where it should be mounted.
332331
void main() {
333-
react_dom.render(geocodesApp({}), querySelector('#content'));
332+
final root = react_dom.createRoot(querySelector('#content'));
333+
root.render(GeocodesApp({}));
334334
}

example/js_components/js_components.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ import 'dart:html';
66
import 'package:js/js.dart';
77
import 'package:react/react.dart' as react;
88
import 'package:react/react_client.dart';
9-
import 'package:react/react_client/react_interop.dart';
9+
import 'package:react/react_client/react_interop.dart' show ReactClass;
1010
import 'package:react/react_dom.dart' as react_dom;
1111

1212
main() {
1313
var content = IndexComponent({});
1414

15-
var root = react_dom.createRoot(querySelector('#content'));
15+
final root = react_dom.createRoot(querySelector('#content'));
1616

17-
root.render(content);
17+
root.render(react.StrictMode({}, content));
1818
}
1919

2020
var IndexComponent = react.registerComponent2(() => new _IndexComponent());
@@ -104,7 +104,7 @@ final SimpleCustom = new ReactJsComponentFactoryProxy(_SimpleCustomComponent);
104104

105105
/// JS interop wrapper class for the component,
106106
/// allowing us to interact with component instances
107-
/// made available via refs or [react_dom.render] calls.
107+
/// made available via refs or render calls.
108108
///
109109
/// This is optional, as you won't always need to access the component's API.
110110
@JS('_SimpleCustomComponent')
Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,42 @@
1-
// ignore_for_file: deprecated_member_use_from_same_package
21
import "dart:html";
32

43
import "package:react/react_dom.dart" as react_dom;
54
import "package:react/react.dart" as react;
65

7-
class _CustomComponent extends react.Component {
6+
class _CustomComponent extends react.Component2 {
87
render() {
98
return react.div({}, props['children']);
109
}
1110
}
1211

13-
var customComponent = react.registerComponent(() => new _CustomComponent());
12+
var customComponent = react.registerComponent2(() => _CustomComponent());
1413

1514
void main() {
16-
react_dom.render(
17-
react.div({}, [
18-
react.div({'key': 'noChildren'}),
19-
react.div({'key': 'emptyList'}, []),
20-
react.div({'key': 'singleItemInList'}, [react.div({})]), // This should produce a key warning
21-
react.div({'key': 'twoItemsInList'}, [react.div({}), react.div({})]), // This should produce a key warning
22-
react.div({'key': 'oneVariadicChild'}, react.div({})),
15+
final root = react_dom.createRoot(querySelector('#content'));
16+
root.render(
17+
react.div({}, [
18+
react.div({'key': 'noChildren'}),
19+
react.div({'key': 'emptyList'}, []),
20+
react.div({'key': 'singleItemInList'}, [react.div({})]), // This should produce a key warning
21+
react.div({'key': 'twoItemsInList'}, [react.div({}), react.div({})]), // This should produce a key warning
22+
react.div({'key': 'oneVariadicChild'}, react.div({})),
2323

24-
// These tests of variadic children won't pass in the ddc until https://github.com/dart-lang/sdk/issues/29904
25-
// is resolved.
26-
// react.div({'key': 'twoVariadicChildren'}, react.div({}), react.div({})),
27-
// react.div({'key': 'fiveVariadicChildren'}, '', react.div({}), '', react.div({}), ''),
24+
// These tests of variadic children won't pass in the ddc until https://github.com/dart-lang/sdk/issues/29904
25+
// is resolved.
26+
// react.div({'key': 'twoVariadicChildren'}, react.div({}), react.div({})),
27+
// react.div({'key': 'fiveVariadicChildren'}, '', react.div({}), '', react.div({}), ''),
2828

29-
customComponent({'key': 'noChildren2'}),
30-
customComponent({'key': 'emptyList2'}, []),
31-
customComponent({'key': 'singleItemInList2'}, [customComponent({})]), // This should produce a key warning
32-
customComponent({'key': 'twoItemsInList2'},
33-
[customComponent({}), customComponent({})]), // This should produce a key warning
34-
customComponent({'key': 'oneVariadicChild2'}, customComponent({'key': '1'})),
29+
customComponent({'key': 'noChildren2'}),
30+
customComponent({'key': 'emptyList2'}, []),
31+
customComponent({'key': 'singleItemInList2'}, [customComponent({})]), // This should produce a key warning
32+
customComponent(
33+
{'key': 'twoItemsInList2'}, [customComponent({}), customComponent({})]), // This should produce a key warning
34+
customComponent({'key': 'oneVariadicChild2'}, customComponent({'key': '1'})),
3535

36-
// These tests of variadic children won't pass in the ddc until https://github.com/dart-lang/sdk/issues/29904
37-
// is resolved.
38-
// customComponent({'key': 'twoVariadicChildren2'}, customComponent({}), customComponent({})),
39-
// customComponent({'key': 'fiveVariadicChildren2'}, '', customComponent({}), '', customComponent({}), ''),
40-
]),
41-
querySelector('#content'));
36+
// These tests of variadic children won't pass in the ddc until https://github.com/dart-lang/sdk/issues/29904
37+
// is resolved.
38+
// customComponent({'key': 'twoVariadicChildren2'}, customComponent({}), customComponent({})),
39+
// customComponent({'key': 'fiveVariadicChildren2'}, '', customComponent({}), '', customComponent({}), ''),
40+
]),
41+
);
4242
}

0 commit comments

Comments
 (0)