react 5.3.0

  • Readme
  • Changelog
  • Example
  • Installing
  • 86

Dart wrapper for React JS #

Pub ReactJS v16.10.1 Build Status React Dart API Docs

Getting Started #

Installation #

If you are not familiar with the ReactJS library, read this react tutorial first.

  1. Install the Dart SDK

     brew install dart
  2. Create a pubspec.yaml file in the root of your project, and add react as a dependency:

     name: your_package_name
     version: 1.0.0
       sdk: ^2.0.0
       react: ^5.0.0
  3. Install the dependencies using pub:

     pub get

Wire things up #


In a .html file where Include the native javascript react and react_dom libraries (provided with this library for compatibility reasons) within your .html file, and add an element with an id to mount your React component into.

Lastly, add the .js file that Dart will generate. The file will be the name of the .dart file that contains your main entrypoint, with .js at the end.

    <!-- ... -->
    <div id="react_mount_point">Here will be react content</div>

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

Note: When serving your application in production, use packages/react/react_with_react_dom_prod.js file instead of the un-minified react.js / react_dom.js files shown in the example above.

Dart App

Once you have an .html file containing the necessary .js files, you can initialize React in the main entrypoint of your Dart application.

import 'dart:html';

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

main() {
  // This should be called once at the beginning of the application.

  // Something to render... in this case a simple <div> with no props, and a string as its children.
  var component = div({}, "Hello world!");

  // Render it into the mount node we created in our .html file.
  react_dom.render(component, querySelector('#react_mount_point'));

Build Stuff #

Using browser native elements #

If you are familiar with React (without JSX extension) React-dart shouldn't surprise you much. All elements are defined as functions that take props as first argument and children as optional second argument. props should implement Map and children is either one React element or List with multiple elements.

var aDiv = div({"className": "something"}, [
  h1({"style": {"height": "20px"}}, "Headline"),
  a({"href":""}, "Something"),
  "Some text"

For event handlers you must provide function that takes a SyntheticEvent (defined in this library).

var aButton = button({"onClick": (SyntheticMouseEvent event) => print(event)});

Defining custom components #

  1. Define custom class that extends Component and implements - at a minimum - render.

     // cool_widget.dart
     import 'package:react/react.dart';
     class CoolWidgetComponent extends Component {
       render() => div({}, "CoolWidgetComponent");
  2. Then register the class so ReactJS can recognize it.

     var CoolWidget = registerComponent(() => new CoolWidgetComponent());

    Warning: registerComponent should be called only once per component and lifetime of application.

  3. Then you can use the registered component similarly as native elements.

     // app.dart
     import 'dart:html';
     import 'package:react/react_client.dart' as react_client;
     import 'package:react/react.dart';
     import 'package:react/react_dom.dart' as react_dom;
     import 'cool_widget.dart';
     main() {
       // This should be called once at the beginning of the application.
       react_dom.render(CoolWidget({}), querySelector('#react_mount_point'));

Custom component with props

// cool_widget.dart

import 'package:react/react.dart';

class CoolWidgetComponent extends Component {
  render() {
    return div({}, props['text']);

var CoolWidget = registerComponent(() => new CoolWidgetComponent());
// app.dart

import 'dart:html';

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

import 'cool_widget.dart';

main() {
  // This should be called once at the beginning of the application.

  react_dom.render(CoolWidget({"text": "Something"}), querySelector('#react_mount_point'));

Custom component with a typed interface

Note: The typed interface capabilities of this library are fairly limited, and can result in extremely verbose implementations. We strongly recommend using the OverReact package - which makes creating statically-typed React UI components using Dart easy.

// cool_widget.dart
typedef CoolWidgetType({String headline, String text, int counter});

var _CoolWidget = registerComponent(() => new CoolWidgetComponent());

CoolWidgetType CoolWidget({String headline, String text, int counter}) {
  return _CoolWidget({'headline':headline, 'text':text});

class CoolWidgetComponent extends Component {
  String get headline => props['headline'];
  String get text => props['text'];
  int get counter => props['counter'];

  render() {
    return div({},
      h1({}, headline),
      span({}, text),
      span({}, counter),
// app.dart

import 'dart:html';

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

import 'cool_widget.dart';

void main() {
  // This should be called once at the beginning of the application.

        headline: "My custom headline",
        text: "My custom text",
        counter: 3,

React Component Lifecycle methods

The Component class mirrors ReactJS' React.Component class, and contains all the same methods.

See: ReactJS Lifecycle Method Documentation for more information.

class MyComponent extends Component {
  void componentWillMount() {}

  void componentDidMount() {}

  void componentWillReceiveProps(Map nextProps) {}

  void componentWillUpdate(Map nextProps, Map nextState) {}

  void componentDidUpdate(Map prevProps, Map prevState) {}

  void componentWillUnmount() {}

  bool shouldComponentUpdate(Map nextProps, Map nextState) => true;

  Map getInitialState() => {};

  Map getDefaultProps() => {};

  render() => div({}, props['text']);

Using refs and findDOMNode

The use of component refs in react-dart is a bit different from React JS.

  • You can specify a ref name in component props and then call ref method to get the referenced element.
  • Return values for Dart components, DOM components and JavaScript components are different.
    • For a Dart component, you get an instance of the Dart class of the component.
    • For primitive components (like DOM elements), you get the DOM node.
    • For JavaScript composite components, you get a ReactElement representing the react component.

If you want to work with DOM nodes of dart or JS components instead, you can call top level findDOMNode on anything the ref returns.

var DartComponent = registerComponent(() => new _DartComponent());
class _DartComponent extends Component {
  render() => div({});

  void someInstanceMethod(int count) {
    window.alert('count: $count');

var ParentComponent = registerComponent(() => new _ParentComponent());
class _ParentComponent extends Component {
  InputElement inputRef; // Returns the DOM node.
  _DartComponent dartComponentRef; // Returns instance of _DartComponent

  void componentDidMount() {
    print(inputRef.value); // Prints "hello" to the console.

    dartComponentRef.someInstanceMethod(5); // Calls the method defined in _DartComponent
    react_dom.findDOMNode(dartComponentRef); // Returns div element rendered from _DartComponent

    react_dom.findDOMNode(this); // Returns root dom element rendered from this component

  render() {
    return div({},
      input({"ref": (ref){ inputRef = ref; }, "defaultValue": "hello"}),
      DartComponent({"ref": (ref) { dartComponentRef = ref; }}),

Example Application #

For more robust examples take a look at our examples.

Unit Testing Utilities #

lib/react_test_utils.dart is a Dart wrapper for the ReactJS TestUtils library allowing for unit tests to be made for React components in Dart.

Here is an example of how to use React React.addons.TestUtils. within a Dart test.

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

class MyTestComponent extends react.Component {
  Map getInitialState() => {'text': 'testing...'};

  render() {
    return react.div({},
        react.button({'onClick': (_) => setState({'text': 'success'})}),
        react.span({'className': 'spanText'}, state['text']),

var myTestComponent = react.registerComponent(() => new MyTestComponent());

void main() {

  test('should click button and set span text to "success"', () {
    var component = react_test_utils.renderIntoDocument(myTestComponent({}));

    // Find button using tag name
    var buttonElement = react_test_utils.findRenderedDOMComponentWithTag(
        component, 'button');

    // Find span using class name
    var spanElement = react_test_utils.findRenderedDOMComponentWithClass(
        component, 'spanText');

    var buttonNode = react_dom.findDOMNode(buttonElement);
    var spanNode = react_dom.findDOMNode(spanElement);

    // Span text should equal the initial state
    expect(spanNode.text, equals('testing...'));

    // Click the button and trigger the onClick event;

    // Span text should change to 'success'
    expect(spanNode.text, equals('success'));

Contributing #

Format using

dartfmt -l 120 -w .

While we'd like to adhere to the recommended line length of 80, it's too too short for much of the code repo written before a formatter was use, causing excessive wrapping and code that's hard to read.

So, we us a line length of 120 instead.

Running Tests #

Dart 2: dart2js

pub run test -p chrome

Or any other browser, e.g. -p firefox.

Dart 2: Dart Dev Compiler ("DDC")

pub run build_runner test -- -p chrome

DDC only works in chrome.

Dart 1: Dart VM

pub run test -p content-shell

Dart 1: dart2js

pub run test -p chrome

Or any other browser platform, e.g. -p firefox.

Dart 1: Dart Dev Compiler ("DDC")

  1. In one terminal, serve the test directory using the dev compiler:
     pub serve test --port=8090 --web-compiler=dartdevc
  2. In another terminal, run the tests, referencing the port the dev compiler is using to serve the test directory:
     pub run test -p chrome --pub-serve=8090
    DDC only works in chrome.

Building React JS Source Files #

Make sure the packages you need are dependencies in package.json then run:

npm install

After modifying files any files in ./js_src/, run:

npm run build

5.3.0 #

  • Unpin the react-redux JS dependency to allow versions 7.1.1 and higher.
  • Run over_react tests as part of the CI process to prevent another situation where changing JS dependencies regressed tightly coupled libs like over_react_redux (like the one that required the 5.2.1 hotfix).
  • #242 Implement StrictMode Component

5.2.1 #

5.2.0 #

  • #190 Fix null value handling in setStateWithUpdater
  • #235 Fix null value handling in getDerivedStateFromError interop
  • #238 Fix js package security vulnerability
  • #236 Expose componentZone to allow overriding the zone in which Component2 lifecycle methods are run, for testing

5.1.1 #

  • Improve the documentation for deprecated Component2 lifecycle methods.

5.1.0 #

Full ReactJS 16.x Component Lifecycle Support

  • The new Component2 class replaces the now deprecated Component class.
    • Faster
    • Improved dev experience
    • Easier to maintain
    • Easier integration with JS libs
    • Supports new lifecycle methods, allowing us to use Concurrent Mode in the future
      • componentWillMount => componentDidMount
      • componentWillReceiveProps => getDerivedStateFromProps (new)
      • componentWillUpdate => getSnapshotBeforeUpdate (new)
      • componentDidCatch / getDerivedStateFromError (new)


  • "Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component."

Improved, stable Context API

  • "Context provides a way to pass data through the component tree without having to pass props down manually at every level. … Context is primarily used when some data needs to be accessible by many components at different nesting levels. Apply it sparingly because it makes component reuse more difficult."


  • "A common pattern in React is for a component to return multiple elements. Fragments let you group a list of children without adding extra nodes to the DOM."
  • Component.render can now return Fragments (multiple children) or other values like strings and lists instead of just a single ReactElement

New and improved ref API: React.createRef

React Redux is now included in the JS bundles and exposed via window.ReactRedux.

Full list of 5.1.0 Changes

5.0.1 #

Pull in 4.9.2 changes that were accidentally reverted as part of 5.0.0.

  • #220 Fix bug where reading dataTransfer sometimes threw during synthetic event conversion

5.0.0 #

ReactJS 16.x Support

  • The underlying .js files provided by this package are now ReactJS version 16.
  • Support for the new / updated lifecycle methods from ReactJS 16 will be released in version 5.1.0.

Full list of 5.0.0 Changes

Full List of Breaking Changes

4.9.2 #

  • #220 Fix bug where reading dataTransfer sometimes threw during synthetic event conversion

4.9.1 #

  • #205 Fix context setter typing to match getter and not fail implicit_casts: false

4.9.0 #

  • #202 Add bindings for transition / animation events
  • #198 Updates in preparation for 5.0.0 release

4.8.1 #

  • #197 Fix Dart component callback refs with typed arguments not working in Dart 2 dynamic ref argument (worked):
      Foo({'ref': (ref) => _fooRef = ref})
    non-dynamic ref argument (did not work):
      Foo({'ref': (FooComponent ref) => _fooRef = ref})

4.8.0 #

  • #181: Remove unnecessary zoning on event handlers that interferes with testing
    • Handlers triggered by real events will now always be called in the root zone.

      In most cases, handlers were already running in the root zone, so this should not affect behavior. See #179 for more details.

    • When testing, you previous had to bind event handlers or callbacks triggered by event handlers to zones when using expect or expectAsync.

        var renderedInstance = renderIntoDocument(
          Button({}, {
            'onButtonPress': Zone.current.bindUnaryCallback(expectAsync((e) {
              // ...
            }, reason: 'onButtonPress not called')),
            'onClick': Zone.current.bindUnaryCallback((e) {
              expect(e.defaultPrevented, isTrue);
        // ...;

      Now, handlers will be called in the zone they're triggered from, which makes testing events easier and more predictable:

        var renderedInstance = renderIntoDocument(
          Button({}, {
            'onButtonPress': expectAsync((e) {
              // ...
            }, reason: 'onButtonPress not called'),
            'onClick': (e) {
              expect(e.defaultPrevented, isTrue);
        // ...;

4.7.1 #

  • #182: Deprecate emptyJsMap:
    • Use newObject() from dart:js_util instead

4.7.0 #

  • #162: Add jsifyAndAllowInterop, deprecate some obsolete JS utils:
    • Deprecate jsify, setProperty, and getProperty; use versions from dart:js_util instead
    • Deprecate EmptyObject; use newObject from dart:js_util instead
  • #170: Reformat with line length of 120 for better readability

4.6.2 #

  • #162: Important Deprecations

    These deprecations are being put in place to prepare consumers for the upcoming 5.0.0 release which will include support for React JS version 16.x

    • react_server.dart and Dart VM server-side rendering
      • Server-side rendering via react_dom_server.dart, though untested, is still in place
    • Legacy context APIs
    • isMounted
    • react_test_utils.SimulateNative
    • String Component.refs
    • Component.replaceStates
    • Component.bind
    • Component.transferComponentState
  • #155: Clean the lint trap.

4.6.1 #

4.6.0 #

  • #152: Format all files using dartfmt.
  • #153: New unconvertJsProps utility function.

4.5.0 #

  • Improvement: Dart 2 compatible!


Serving / Viewing React Dart Examples #

  1. Run pub get in your terminal.
  2. Run pub serve example --web-compiler=dartdevc.
  3. Open Chrome.
  4. Navigate to http://localhost:8080

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:

  react: ^5.3.0

2. Install it

You can install packages from the command line:

with pub:

$ pub get

with Flutter:

$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:

import 'package:react/react.dart';
Describes how popular the package is relative to other packages. [more]
Code health derived from static analysis. [more]
Reflects how tidy and up-to-date the package is. [more]
Weighted score of the above. [more]
Learn more about scoring.

We analyzed this package on May 24, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.1
  • pana: 0.13.8-dev

Health suggestions

Fix lib/react_client.dart. (-24.85 points)

Analysis of lib/react_client.dart reported 57 hints, including:

line 116 col 49: Unnecessary new keyword.

line 124 col 20: Unnecessary new keyword.

line 126 col 24: Unnecessary new keyword.

line 175 col 29: Unnecessary new keyword.

line 208 col 24: Unnecessary new keyword.

Fix lib/react.dart. (-11.33 points)

Analysis of lib/react.dart reported 24 hints, including:

line 167 col 20: Unnecessary new keyword.

line 172 col 24: Unnecessary new keyword.

line 176 col 18: Unnecessary new keyword.

line 181 col 18: Unnecessary new keyword.

line 253 col 18: Unnecessary new keyword.

Fix lib/react_client/js_backed_map.dart. (-1.99 points)

Analysis of lib/react_client/js_backed_map.dart reported 4 hints:

line 28 col 30: Unnecessary new keyword.

line 34 col 42: Unnecessary new keyword.

line 37 col 48: Unnecessary new keyword.

line 151 col 12: Unnecessary new keyword.

Fix additional 10 files with analysis or formatting issues. (-5.98 points)

Additional issues in the following files:

  • lib/react_client/bridge.dart (3 hints)
  • lib/react_client/react_interop.dart (3 hints)
  • lib/react_client/js_interop_helpers.dart (2 hints)
  • lib/src/context.dart (2 hints)
  • lib/react_dom.dart (1 hint)
  • lib/src/ddc_emulated_function_name_bug.dart (1 hint)
  • lib/react_dom_server.dart (Run dartfmt to format lib/react_dom_server.dart.)
  • lib/react_test_utils.dart (Run dartfmt to format lib/react_test_utils.dart.)
  • lib/src/react_client/dart2_interop_workaround_bindings.dart (Run dartfmt to format lib/src/react_client/dart2_interop_workaround_bindings.dart.)
  • lib/src/react_client/event_prop_key_to_event_factory.dart (Run dartfmt to format lib/src/react_client/event_prop_key_to_event_factory.dart.)


Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.4.0 <3.0.0
js ^0.6.0 0.6.1+1
meta ^1.1.6 1.1.8
Dev dependencies
args ^1.5.1
build_runner ^1.6.5
build_test ^0.10.8
build_web_compilers ^2.1.4
dependency_validator ^1.2.0
matcher ^0.12.5
test ^1.6.5