Skip to content
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

CPLAT-4303: React 16 New Context #160

Merged
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
f84c15d
Deprecate js_interop_helpers in favor of package:js/js_util.dart
greglittlefield-wf Dec 29, 2016
0713393
Un-deprecate jsify, fix deprecations
greglittlefield-wf Dec 29, 2016
77f9b91
Bump JS package version to the one that exposes js_util.dart
greglittlefield-wf Dec 30, 2016
bfc53e5
Revert likely breaking change to emptyJsMap and deprecate it instead
greglittlefield-wf Dec 30, 2016
68008b4
Merge branch 'use_js_util' into js_components
greglittlefield-wf Dec 30, 2016
4a16ba4
Add common factory tests for DOM/Dart components
greglittlefield-wf Dec 30, 2016
c174de2
Add factory proxy for JS components
greglittlefield-wf Dec 30, 2016
86913c2
Add JS factory tests
greglittlefield-wf Dec 30, 2016
f93f521
Add jsifyAndAllowInterop, deprecate jsify
greglittlefield-wf Dec 30, 2016
c346708
Use jsifyAndAllowInterop
greglittlefield-wf Dec 30, 2016
f20c287
Clean up simulators slightly
greglittlefield-wf Dec 30, 2016
1a7b5ff
By default, convert DOM props passed to JS components
greglittlefield-wf Dec 30, 2016
e107f93
Throw if backing JS class is null
greglittlefield-wf Jan 2, 2017
992586e
Add common event handler tests
greglittlefield-wf Jan 2, 2017
cd9d840
Add wrapEventHandler convenience method
greglittlefield-wf Jan 2, 2017
f0c12fe
Add demo on using JS components
greglittlefield-wf Jan 2, 2017
56b1d4b
Add index to example directory
greglittlefield-wf Jan 2, 2017
63ab345
Add notice about seeing Dart source
greglittlefield-wf Jan 2, 2017
e7209e6
Include full dart-lang/sdk license text in attribution
greglittlefield-wf Jan 2, 2017
273b915
Merge remote-tracking branch 'origin/master' into js_components
greglittlefield-wf Feb 19, 2019
8f50741
Fix lints
greglittlefield-wf Feb 19, 2019
dd34bad
Post-merge fixes
greglittlefield-wf Feb 19, 2019
0f38687
dartfmt
greglittlefield-wf Feb 19, 2019
e611912
Fix example
greglittlefield-wf Feb 19, 2019
2a44115
inital pass at new context
kealjones-wk Feb 19, 2019
c358278
Fix js_factory_test.js div creation
kealjones-wk Feb 20, 2019
5a8768d
ReactJsComponentFactoryProxy is WORKING!
kealjones-wk Feb 26, 2019
9967b32
Merge branch 'master' into react-16-new-context
kealjones-wk Feb 27, 2019
785615e
Fix contextType in release mode and Update tests
kealjones-wk Feb 27, 2019
06ebacf
Update contextType to getter/setter to get doc comment to showing
kealjones-wk Feb 27, 2019
fe505af
Add tests for context value types
kealjones-wk Feb 28, 2019
22c4e8b
remove unused imports from new tests
kealjones-wk Feb 28, 2019
d86c53b
Merge 5.0.0-wip
kealjones-wk Feb 28, 2019
57d8396
cleanup and run dartfmt
kealjones-wk Feb 28, 2019
dc57dd4
push updated bundles
kealjones-wk Feb 28, 2019
a56e1a7
Dart1 Compatability fixes
kealjones-wk Feb 28, 2019
e2863ed
more dart 1 compat stuff
kealjones-wk Feb 28, 2019
33b8e67
ignore .vscode :|
kealjones-wk Feb 28, 2019
8c96836
Address CR Feedback
kealjones-wk Mar 4, 2019
5c21ac8
Add new context to Component2
kealjones-wk Mar 16, 2019
1351180
undo changes to JsBackedMap and update tests
kealjones-wk Mar 16, 2019
cb748ff
fix dart js
kealjones-wk Mar 17, 2019
eca1297
Cleanup and address some feedback
kealjones-wk Mar 17, 2019
06e0657
dart format 120 and js package update
kealjones-wk Mar 17, 2019
a4ab9f9
Merge 5.0.0-wip
kealjones-wk Mar 17, 2019
752150e
remove typing from interop, due to strange issue it created
kealjones-wk Mar 17, 2019
e6e5374
Undo some type loosening
kealjones-wk Mar 18, 2019
3668628
fix context example
kealjones-wk Mar 18, 2019
40f96b7
fix dartfmt
kealjones-wk Mar 18, 2019
063b8f1
fix react dev tools and tests
kealjones-wk Mar 18, 2019
a90610b
re-add legacy context to example
kealjones-wk Mar 18, 2019
e2629f4
dartfmt
kealjones-wk Mar 18, 2019
a706cda
change usages of js_interop_helpers.dart to dart:js_util and more
kealjones-wk Mar 18, 2019
ce8b15d
dartfmt
kealjones-wk Mar 18, 2019
5c6e73c
update to better support calculateChangedBits
kealjones-wk Mar 19, 2019
cec53a5
dartfmt
kealjones-wk Mar 19, 2019
11a98f2
add tests for createContext calculateChangedBits
kealjones-wk Mar 19, 2019
5f25108
re-order wrappers to top of components
kealjones-wk Mar 19, 2019
42c7f1f
Fix some interop issues when using dart2js
kealjones-wk Mar 19, 2019
95863b5
add shouldComponentUpdate with 3rd argument
kealjones-wk Mar 20, 2019
b16a8bc
dartfmt
kealjones-wk Mar 20, 2019
4044e5c
addressing more cr feedback
kealjones-wk Mar 20, 2019
b85d5ff
Merge 5.0.0-wip resolve merge conflicts
kealjones-wk Mar 20, 2019
0b60aab
dartfmt
kealjones-wk Mar 20, 2019
9fd46f8
Update js Components example and add link
kealjones-wk Mar 20, 2019
f3353e4
Merge ‘upstream/5.0.0-wip' into react-16-new-context
aaronlademann-wf Mar 21, 2019
e26827d
Update Js Example to use some Material UI Components
kealjones-wk Mar 22, 2019
745a0b7
Address some CR feedback by aaron
kealjones-wk Mar 22, 2019
71bf2ca
address more feedback
kealjones-wk Mar 25, 2019
34b95cc
add small comments to example
kealjones-wk Mar 25, 2019
f3ad312
Address CR Feedback
kealjones-wk Apr 1, 2019
d38c570
address cr and Add contextType Lifecycle tests
kealjones-wk Apr 3, 2019
45ed03a
Update build config for dart2js, use build_runner to run dart2js tests
greglittlefield-wf Apr 2, 2019
bb67481
Update typing, remove redundant `as dynamic` JsBackedMap case
greglittlefield-wf Apr 3, 2019
bd28d30
add a context.consumer child lifecycle test
kealjones-wk Apr 3, 2019
81dc26a
Merge pull request #3 from greglittlefield-wf/react-16-new-context
kealjones-wk Apr 3, 2019
9d6045b
dartfmt
kealjones-wk Apr 3, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ pubspec.lock
.packages
node_modules/
.dart_tool
.vscode
20 changes: 20 additions & 0 deletions example/js_components/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>JS Components - react-dart Examples</title>
</head>
<body>
<em>See Dart source for more info</em>

<div id="content"></div>

<script src="packages/react/react.js"></script>
<script src="packages/react/react_dom.js"></script>

<!-- Where the JS React components are declared. -->
<script src="js_components.js"></script>

<script defer src="js_components.dart.js"></script>
</body>
</html>
83 changes: 83 additions & 0 deletions example/js_components/js_components.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
@JS()
library js_components;

import 'dart:html';
import 'dart:math';

import 'package:js/js.dart';
import 'package:react/react.dart' as react;
import 'package:react/react_client.dart';
import 'package:react/react_client/react_interop.dart';
import 'package:react/react_dom.dart' as react_dom;

var fooRef;

main() {
aaronlademann-wf marked this conversation as resolved.
Show resolved Hide resolved
setClientConfiguration();

var content = Foo({
// Foo forwards its props to its DOM nodes, so you can set
// DOM props here and they'll work just how you'd expect them to.
'title': 'Hey, quit hovering me!',
'style': {
'color': ['#f00', '#0f0', '#00f'][new Random().nextInt(3)]
},
'onMouseEnter': (react.SyntheticMouseEvent e) {
print(e.runtimeType);
print('Entered!');
},

// Refs work the same, only you get back the JS component instance.
// See below for how you can use this.
'ref': (ref) {
fooRef = ref;
},

// Props specific to the component can be specified as well!
'foo': 'bar',
// // Non-DOM event handlers props can't be automatically wrapped with
// // conversion logic, so this has to be done manually if you need
// // access to the Dart [react.SyntheticEvent] and not the JS one.
// //
// // See [wrapEventHandler] docs for more info.
// 'onButtonClick': wrapEventHandler(_handleButtonClick, 'onClick'),
});

react_dom.render(content, querySelector('#content'));

// If you need to access a component instance, say,
// to call an API method, you can do so by writing
// a JS interop wrapper class.
print((fooRef as FooComponent).getFoo());
}

void _handleButtonClick(react.SyntheticMouseEvent event) {
print('Clicked!');
}

/// The JS component class.
///
/// Private since [Foo] will be used instead.
///
/// Accessible via `Foo.type`.
@JS('Foo')
external ReactClass get _Foo;

/// A factory for the "Foo" JS components class that allows it
/// to be used via Dart code.
///
/// Use this to render instances of the component from within Dart code.
///
/// This converts the Dart props [Map] passed into it in the
/// the same way props are converted for DOM components.
final Foo = new ReactJsComponentFactoryProxy(_Foo);

/// JS interop wrapper class for the component,
/// allowing us to interact with component instances
/// made available via refs or [react_dom.render] calls.
///
/// This is optional, as you won't always need to access the component's API.
@JS()
class FooComponent {
external String getFoo();
}
23 changes: 23 additions & 0 deletions example/js_components/js_components.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
var Foo = React.createClass({
render: function() {
// Equivalent to ES6:
// var {foo, onButtonClick, ...rest} = this.props;
var foo = this.props.foo;
var onButtonClick = this.props.onButtonClick;
var rest = Object.assign({}, this.props);
delete rest.foo;
delete rest.onButtonClick;

return React.createElement("div", {}, [rest,
React.createElement("h4", {}, 'Foo component'),
React.createElement("p", {}, 'value of props.foo: ', foo),
React.createElement("button", {onClick: onButtonClick}, 'button')
]);
},

getFoo: function() {
return this.props.foo;
}
});

window.Foo = Foo;
62 changes: 32 additions & 30 deletions example/test/react_test_components.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import "dart:async";
import 'dart:convert';

import "package:react/react.dart" as react;
import 'package:react/react_client.dart';
import "package:react/react_dom.dart" as react_dom;

class _HelloComponent extends react.Component {
Expand Down Expand Up @@ -169,15 +171,17 @@ class _MainComponent extends react.Component {

var mainComponent = react.registerComponent(() => new _MainComponent());

var TestContext = createContext({
'dartClass': react.Component,
'map': {'test': true},
'renderCount': 0
});

class _ContextComponent extends react.Component {
@override
Iterable<String> get childContextKeys => const ['foo', 'bar', 'renderCount'];

@override
Map<String, dynamic> getChildContext() => {
'foo': {'object': 'with value'},
'bar': true,
'renderCount': this.state['renderCount']
getInitialState() => {
'dartClass': react.Component,
'map': {'test': true},
'renderCount': 0
};

render() {
Expand All @@ -191,54 +195,52 @@ class _ContextComponent extends react.Component {
'onClick': _onButtonClick
}, 'Redraw'),
react.br({'key': 'break1'}),
'ContextComponent.getChildContext(): ',
getChildContext().toString(),
'TestContext.Provider props.value: $state',
react.br({'key': 'break2'}),
react.br({'key': 'break3'}),
props['children'],
TestContext.Provider(
{'key': 'tcp', 'value': this.state},
props['children'],
),
]);
}

_onButtonClick(event) {
this.setState({'renderCount': (this.state['renderCount'] ?? 0) + 1});
this.setState({'renderCount': this.state['renderCount'] + 1});
}
}

var contextComponent = react.registerComponent(() => new _ContextComponent());

class _ContextConsumerComponent extends react.Component {
@override
Iterable<String> get contextKeys => const ['foo'];

render() {
return react.ul({
'key': 'ul'
}, [
'ContextConsumerComponent.context: ',
context.toString(),
react.br({'key': 'break1'}),
react.br({'key': 'break2'}),
props['children'],
]);
return TestContext.Consumer({}, (value) {
return react.ul({
'key': 'ul'
}, [
'TestContext.Consumer: value = ${value}',
react.br({'key': 'break1'}),
react.br({'key': 'break2'}),
props['children'],
]);
});
}
}

var contextConsumerComponent =
react.registerComponent(() => new _ContextConsumerComponent());

class _GrandchildContextConsumerComponent extends react.Component {
@override
Iterable<String> get contextKeys => const ['renderCount'];
class _ContextTypeConsumerComponent extends react.Component {
var contextType = TestContext;

render() {
return react.ul({
'key': 'ul'
}, [
'GrandchildContextConsumerComponent.context: ',
context.toString(),
'Using Component.contextType: this.context = ${this.context}',
]);
}
}

var grandchildContextConsumerComponent =
react.registerComponent(() => new _GrandchildContextConsumerComponent());
react.registerComponent(() => new _ContextTypeConsumerComponent());
26 changes: 3 additions & 23 deletions js_src/_dart_helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,29 +50,9 @@ function _createReactDartComponentClass(dartInteropStatics, componentStatics, js
}
}

// React limits the accessible context entries
// to the keys specified in childContextTypes/contextTypes.
var childContextKeys = jsConfig && jsConfig.childContextKeys;
var contextKeys = jsConfig && jsConfig.contextKeys;

if (childContextKeys && childContextKeys.length !== 0) {
ReactDartComponent.childContextTypes = {};
for (var i = 0; i < childContextKeys.length; i++) {
ReactDartComponent.childContextTypes[childContextKeys[i]] = React.PropTypes.object;
}
// Only declare this when `childContextKeys` is non-empty to avoid unnecessarily
// creating interop context objects for components that won't use it.
ReactDartComponent.prototype['getChildContext'] = function() {
return dartInteropStatics.handleGetChildContext(this.dartComponent);
};
}

if (contextKeys && contextKeys.length !== 0) {
ReactDartComponent.contextTypes = {};
for (var i = 0; i < contextKeys.length; i++) {
ReactDartComponent.contextTypes[contextKeys[i]] = React.PropTypes.object;
}
}
if (jsConfig && jsConfig.contextType) {
ReactDartComponent.contextType = jsConfig.contextType;
}

return ReactDartComponent;
}
Expand Down
Loading