diff --git a/.babelrc b/.babelrc index 2d8deea..583a4b1 100644 --- a/.babelrc +++ b/.babelrc @@ -1,10 +1,15 @@ { "presets": [ - "react", - "es2015" + [ + "@babel/preset-env", { + targets: {node: 'current'}, + }, + ], + "@babel/preset-react", + "@babel/preset-flow", ], "plugins": [ - "transform-class-properties" + "@babel/plugin-proposal-class-properties" ], "env": { "test": { diff --git a/.eslintrc.js b/.eslintrc.js index 018a703..83a3f53 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,15 +1,6 @@ module.exports = { parser: 'babel-eslint', - 'extends': './node_modules/fbjs-scripts/eslint/.eslintrc.js', - plugins: [ - 'react', - ], - globals: { - ReactComponent: true, - React$Component: true, - ReactClass: true, - React$Element: true, - }, + plugins: ['react'], rules: { 'object-curly-spacing': [2, 'never'], 'react/jsx-uses-react': 2, diff --git a/.flowconfig b/.flowconfig index c8f5f45..71b41a5 100644 --- a/.flowconfig +++ b/.flowconfig @@ -1,4 +1,8 @@ [ignore] +# stop checking the stack reconciler in the new world :D +.*/src/index.js +.*/src/stack + # Ignore react and fbjs where there are overlaps, but don't ignore # anything that react-native relies on .*/node_modules/fbjs.* @@ -25,8 +29,6 @@ [include] [libs] -types/fbjs.js -types/firmata.js [options] suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-0]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\) diff --git a/.gitignore b/.gitignore index 7d33764..f389c79 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ node_modules .DS_Store *.log +.buckd +lib diff --git a/.travis.yml b/.travis.yml index e2e7a3f..c590f08 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ --- language: node_js node_js: -- 5 +- 8 cache: directories: - node_modules @@ -17,7 +17,7 @@ before_install: echo "Only docs were updated, stopping build process." exit 0 else - npm install flow-bin@0.22 + npm install flow-bin@0.94 fi script: - | @@ -28,7 +28,7 @@ script: elif [ "$TEST_TYPE" = test ]; then npm test else - ./scripts/test $TEST_TYPE + npm test -- $TEST_TYPE fi env: - CXX=g++-4.8 TEST_TYPE=test diff --git a/README.md b/README.md index 797616c..19f1ee8 100644 --- a/README.md +++ b/README.md @@ -33,18 +33,21 @@ const LOW = 0; class Application extends React.Component { constructor(props) { super(props); - this.state = { - value: 0, - _timer: null, - }; + this.state = {value: 0}; + this._timer = null; } componentDidMount() { - this.state._timer = setInterval(_ => ( - this.setState({value: this.state.value === HIGH ? LOW : HIGH}) + this._timer = setInterval(_ => ( + this.setState(prevState => ({value: prevState.value === HIGH ? LOW : HIGH})) ), this.props.interval); } + componentWillUnmount() { + clearInterval(this._timer); + this._timer = null; + } + render() { return ( @@ -53,7 +56,7 @@ class Application extends React.Component { } var PORT = '/dev/tty.usbmodem1411'; -ReactHardware.render(, PORT); +ReactHardware.render(, PORT); ``` While this is unquestionably more code than it’s Johnny-Five or Sketch @@ -63,7 +66,7 @@ we introduced the concept of a flashing LED, hard-coded naively into the global state. Let’s now extract the idea of a flashing LED into something we can share with our team or even on npm. -``` javascript +``` jsx import React from 'react'; import ReactHardware, {Board, Led} from 'react-hardware'; @@ -73,18 +76,24 @@ const LOW = 0; class FlashingLed extends React.Component { constructor(props) { super(props); - this.state = { - value: 0, - _timer: null, + this.state = {value: 0}; + this._timer = null; + this.defaultProps = { + interval: 1000, }; } componentDidMount() { - this.state._timer = setInterval(_ => ( - this.setState({value: this.state.value === HIGH ? LOW : HIGH}) + this._timer = setInterval(_ => ( + this.setState(prevState => ({value: prevState.value === HIGH ? LOW : HIGH})) ), this.props.interval); } + componentWillUnmount() { + clearInterval(this._timer); + this._timer = null; + } + render() { return ( diff --git a/examples/basic-hook/index.js b/examples/basic-hook/index.js new file mode 100644 index 0000000..25ca7e6 --- /dev/null +++ b/examples/basic-hook/index.js @@ -0,0 +1,40 @@ +/** + * Blinking LED. + * This example blinks the Arduino Uno built-in LED on pin 13 every 1 second. + */ + +import * as React from 'react'; +import {getPort} from '../port'; +import ReactHardware from '../../src'; + +// thanks Dan. https://overreacted.io/making-setinterval-declarative-with-react-hooks/ +function useInterval(callback, delay) { + const savedCallback = React.useRef(); + + // Remember the latest callback. + React.useEffect(() => { + savedCallback.current = callback; + }, [callback]); + + // Set up the interval. + React.useEffect(() => { + function tick() { + savedCallback.current(); + } + if (delay !== null) { + let id = setInterval(tick, delay); + return () => clearInterval(id); + } + }, [delay]); +} + +const FlashingLedHook = () => { + const [value, setState] = React.useState(1); + useInterval(() => setState(value === 0 ? 1 : 0), 1000); + + return ; +}; + +ReactHardware.render(, getPort(), inst => { + console.log('Rendered <%s />', 'FlashingLedHook'); +}); diff --git a/examples/basic/index.js b/examples/basic/index.js index d0c802c..f0a70dc 100644 --- a/examples/basic/index.js +++ b/examples/basic/index.js @@ -3,16 +3,12 @@ * This example blinks the Arduino Uno built-in LED on pin 13 every 1 second. */ -import React, {Component} from 'react'; +import * as React from 'react'; import {getPort} from '../port'; import ReactHardware from '../../src'; -class FlashingLed extends Component { - constructor(props, context) { - super(props, context); - - this.state = {value: 1}; - } +class FlashingLed extends React.Component<{}, {value: number}> { + state = {value: 1}; componentDidMount() { setInterval(() => { @@ -23,20 +19,10 @@ class FlashingLed extends Component { } render() { - return ( - - ); + return ; } } -ReactHardware.render( - , - getPort(), - (inst) => { - console.log('Rendered <%s />', FlashingLed.name); - } -); +ReactHardware.render(, getPort(), inst => { + console.log('Rendered <%s />', FlashingLed.name); +}); diff --git a/examples/button/index.js b/examples/button/index.js index 4dffde8..2fb2d1a 100644 --- a/examples/button/index.js +++ b/examples/button/index.js @@ -6,6 +6,11 @@ * and is as low level as you can get. * * Provided composite components like