• Stars
    star
    412
  • Rank 105,024 (Top 3 %)
  • Language
    JavaScript
  • License
    BSD 2-Clause "Sim...
  • Created about 11 years ago
  • Updated 25 days ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Dart Bindings for React JS

Dart wrapper for React JS

Pub ReactJS v17.0.1 Dart CI React Dart API Docs

Thanks to the folks at Vacuumlabs for creating this project! ❀️

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
    environment:
      sdk: ^2.11.0
    dependencies:
      react: ^6.0.0
  3. Install the dependencies using pub:

    dart pub get

Wire things up

HTML

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

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.

<html>
  <head>
    <!-- ... -->
  </head>
  <body>
    <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>
  </body>
</html>

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.dart';
import 'package:react/react_dom.dart' as react_dom;

main() {
  // 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.com"}, "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 Component2 and implements - at a minimum - render.

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

    var CoolWidget = registerComponent2(() => CoolWidgetComponent());

    Warning: registerComponent2 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.dart';
    import 'package:react/react_dom.dart' as react_dom;
    
    import 'cool_widget.dart';
    
    main() {
      react_dom.render(CoolWidget({}), querySelector('#react_mount_point'));
    }

Custom component with props

// cool_widget.dart

import 'package:react/react.dart';

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

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

import 'dart:html';

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

import 'cool_widget.dart';

main() {
  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 = registerComponent2(() => CoolWidgetComponent());

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

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

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

import 'dart:html';

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

import 'cool_widget.dart';

void main() {
  react_dom.render(
    myComponent(
        headline: "My custom headline",
        text: "My custom text",
        counter: 3,
    ),
    querySelector('#react_mount_point')
  );
}

React Component Lifecycle methods

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

See: ReactJS Lifecycle Method Documentation for more information.

class MyComponent extends Component2 {
  @override
  void componentWillMount() {}

  @override
  void componentDidMount() {}

  @override
  void componentWillReceiveProps(Map nextProps) {}

  @override
  void componentWillUpdate(Map nextProps, Map nextState) {}

  @override
  void componentDidUpdate(Map prevProps, Map prevState) {}

  @override
  void componentWillUnmount() {}

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

  @override
  Map getInitialState() => {};

  @override
  Map getDefaultProps() => {};

  @override
  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 = registerComponent2(() => _DartComponent());
class _DartComponent extends Component2 {
  @override
  render() => div({});

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

var ParentComponent = registerComponent2(() => _ParentComponent());
class _ParentComponent extends Component2 {
  final inputRef = createRef<InputElement>(); // inputRef.current is the DOM node.
  final dartComponentRef = createRef<_DartComponent>(); // dartComponentRef.current is the instance of _DartComponent

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

    dartComponentRef.current.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
  }

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

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 package:react/react_test_utils.dart within a Dart test.

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

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

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

var myTestComponent = react.registerComponent2(() => 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
    react_test_utils.Simulate.click(buttonNode);

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

Contributing

Format using

dart format -l 120 .

While we'd like to adhere to the recommended line length of 80, it's 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 use a line length of 120 instead.

Running Tests

dart2js

dart run build_runner test --release -- --preset dart2js

NOTE: When using Dart SDK < 2.14.0, use --preset dart2js-legacy instead.

Dart Dev Compiler ("DDC")

dart run build_runner test -- --preset dartdevc

NOTE: When using Dart SDK < 2.14.0, use --preset dartdevc-legacy instead.

Building React JS Source Files

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

yarn install

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

yarn run build

More Repositories

1

go-datastructures

A collection of useful, performant, and threadsafe Go datastructures.
Go
7,607
star
2

eva

A distributed database-system implementing an entity-attribute-value data-model that is time-aware, accumulative, and atomically consistent
Clojure
564
star
3

over_react

A library for building statically-typed React UI components using Dart.
Dart
427
star
4

frugal

Thrift improved
Go
140
star
5

built_redux

an implementation of redux written in dart that enforces immutability
Dart
125
star
6

dart_dev

Centralized tooling for Dart projects. Consistent interface across projects. Easily configurable.
Dart
75
star
7

dart_codemod

A library that makes it easy to write and run automated code modifications on a codebase.
Dart
60
star
8

state_machine

Easily create a finite state machine and define legal state transitions. Listen to state entrances, departures, and transitions.
Dart
60
star
9

opentelemetry-dart

Dart
57
star
10

dependency_validator

A tool to help you find missing, under-promoted, over-promoted, and unused dependencies.
Dart
56
star
11

go-rest

A Go library that makes it easy to build a flexible and (mostly) unopinionated REST API with little ceremony.
Go
49
star
12

furious

Fast and modular async task library for Google App Engine.
Python
37
star
13

w_flux

A Dart app architecture library with uni-directional data flow inspired by RefluxJS and Facebook's Flux.
Dart
25
star
14

morphe

A Clojure utility for defining and applying aspects to function definitions.
Clojure
25
star
15

w_transport

A platform-agnostic transport library for sending and receiving data over HTTP and WebSocket.
Dart
22
star
16

aws-lambda-fsm-workflows

A Python framework for developing finite state machine-based workflows on AWS Lambda.
Python
21
star
17

dart_to_js_script_rewriter

A pub transformer that Rewrites Dart script tags to JavaScript script tags, eliminating 404s and speeding up initial loads. Use when building for deployment.
Dart
21
star
18

w_module

Base module classes with a well defined lifecycle for modular Dart applications.
Dart
19
star
19

platform_detect

A library for detecting browser and platform type and version.
Dart
19
star
20

go-hystrimp

An ergonomic implementation of Hystrix fault-tolerance principles for Go developers.
Go
19
star
21

fluri

Fluri is a fluent URI library for Dart built to make URI mutation easy.
Dart
18
star
22

gae-financials

Simple demo app to illustrate developing real world applications on Google App Engine.
Python
18
star
23

thrift-nats

A library that adds support for using NATS as a Thrift RPC transport.
Go
14
star
24

wf-uicomponents

Mobile-optimized, composable UI components that support a rich HTML5 user experience.
JavaScript
13
star
25

wGulp

Opinionated Suite of Gulp Tasks for JavaScript and TypeScript projects.
JavaScript
12
star
26

scip-dart

Dart
11
star
27

utiliva

A collection of helpful little utilities for Clojure.
Clojure
11
star
28

webdev_proxy

A simple HTTP proxy for the webdev serve command (a tool authored by the dart team) that adds support for rewriting certain requests, namely rewriting 404s to instead serve the root index (/index.html). This allows developers to work on browser applications (like our own) that use HTML5 routing while still being able to refresh and/or navigate directly to deep links.
JavaScript
11
star
29

r_tree

A recursive RTree library written in Dart.
Dart
10
star
30

opentracing_dart

This library is the Open Tracing API written in Dart. It is intended for use both on the server and in the browser.
Dart
10
star
31

w_common

A collection of helpful utilities for use in Dart projects.
Dart
10
star
32

styleguide

9
star
33

pdfjs_dart

Dart bindings for Mozilla's PDF.js library
JavaScript
7
star
34

flowgraph

A Clojure library for fast, concurrent, asynchronous data processing using directed graphs. Decursus supports cyclic graphs. Though it is not distributed, it does have primitive tools for minimizing communication overhead in the event that some processing steps involve calls to distributed resources.
Clojure
6
star
35

wf-common

A collection of helpful utilities for use in JavaScript projects.
JavaScript
6
star
36

over_react_test

A library for testing OverReact components
Dart
6
star
37

dart_transformer_utils

Utilities relating to code generation, Dart analyzer, logging, etc. for use in Pub transformers.
Dart
6
star
38

w_service

Dart
5
star
39

react_testing_library

Dart bindings for the JS dom-testing-library and react-testing-library packages, which provide simple and complete DOM/React testing utilities that encourage good testing practices.
Dart
5
star
40

tesserae

A Clojure library that abstracts over promises, futures, delays, etc. with chaining and cancellations.
Clojure
4
star
41

w-mobile-kit

A Swift library containing various custom UI components to provide functionality outside of the default libraries.
Swift
4
star
42

wf-grunt

Opinionated Suite of Grunt Tasks for JavaScript and TypeScript projects.
JavaScript
4
star
43

goverge

A golang multi package coverage reporting tool.
Python
3
star
44

autoPaw

JavaScript
3
star
45

paw

A touch / touch gesture simulation library for JavaScript.
JavaScript
3
star
46

sockjs-dart-client

A Dart client library for SockJS.
Dart
3
star
47

workiva_analysis_options

Workiva's shared Dart static analysis options
Dart
3
star
48

lsif_indexer

Dart
2
star
49

eva-client-service

The Eva client service is an Eva peer which exposes Eva functionality to other languages through a REST interface.
Java
2
star
50

over_react_codemod

Codemods to help consumers of over_react automate the migration of UI component code.
Dart
2
star
51

font_face_observer

Load and unload fonts in the browser with a Promise based API. Simple, small and efficient. It will use the FontFace api if available, otherwise it falls back to a Dart port of https://github.com/bramstein/fontfaceobserver
Dart
2
star
52

sockjs_client_wrapper

A Dart wrapper around the SockJS Client. Uses the js Dart package to interop with the JS lib.
JavaScript
2
star
53

eva-catalog

Provides a central repository (and client) for handling the configuration maps used to connect to EVA
Clojure
1
star
54

lazy-tables

A set of tools for lazy relational algebra
Clojure
1
star
55

test_html_builder

Dart builder that generates HTML files from templates for dart tests.
Dart
1
star
56

abide

A command line tool to manage analysis_options.yaml and check if it abides by requirements.
Dart
1
star
57

barometer

A thin clojure wrapper over Coda Hale's metrics library for the JVM.
Clojure
1
star
58

ichnaie

A handful of Clojure utilities for easing project integration with the OpenTracing API
Clojure
1
star
59

recide

Provides utilities for defining standard ex-info forms, as well as the capacity for checking at compile-time that they are being used as intended
Clojure
1
star
60

dpx

Dart
1
star