diff --git a/package.json b/package.json index ca4d0b4..113cad3 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "babel-preset-react-native": "^1.4.0", "browserify": "^13.0.0", "create-react-class": "^15.6.3", - "react": "^16.2.0", - "react-dom": "^16.2.0" + "react": "^16.7.0-alpha.0", + "react-dom": "^16.7.0-alpha.0" } } diff --git a/src/createAnimatedComponent.js b/src/createAnimatedComponent.js index f757b0f..14cfac2 100644 --- a/src/createAnimatedComponent.js +++ b/src/createAnimatedComponent.js @@ -7,33 +7,40 @@ * * @flow */ -'use strict'; +"use strict"; -var React = require('react'); -var AnimatedProps = require('./AnimatedProps'); -var ApplyAnimatedValues = require('./injectable/ApplyAnimatedValues'); +var React = require("react"); +var AnimatedProps = require("./AnimatedProps"); +var ApplyAnimatedValues = require("./injectable/ApplyAnimatedValues"); -function createAnimatedComponent(Component: any): any { - class AnimatedComponent extends React.Component { - _propsAnimated: AnimatedProps; +const { + useState, + useRef, + useCallback, + useEffect, + forwardRef, + useImperativeMethods, +} = React; - componentWillUnmount() { - this._propsAnimated && this._propsAnimated.__detach(); - } +function createAnimatedComponent(Component: any): any { + const AnimatedComponent = forwardRef((props, ref) => { + const isMountedRef = useRef(true); + const propsAnimatedRef = useRef(null); + const componentRef = useRef(null); + const forceUpdate = useState(null)[1]; - setNativeProps(props) { - var didUpdate = ApplyAnimatedValues.current(this.componentRef, props, this); + const setNativeProps = useCallback(props => { + const didUpdate = ApplyAnimatedValues.current( + componentRef.current, + props + ); if (didUpdate === false) { - this.forceUpdate(); + isMountedRef.current && forceUpdate(); } - } + }, []); - componentWillMount() { - this.attachProps(this.props); - } - - attachProps(nextProps) { - var oldPropsAnimated = this._propsAnimated; + const attachProps = useCallback(nextProps => { + let oldPropsAnimated = propsAnimatedRef.current; // The system is best designed when setNativeProps is implemented. It is // able to avoid re-rendering and directly set the attributes that @@ -41,17 +48,11 @@ function createAnimatedComponent(Component: any): any { // native components. If you want to animate a composite component, you // need to re-render it. In this case, we have a fallback that uses // forceUpdate. - var callback = () => { - var didUpdate = ApplyAnimatedValues.current(this.componentRef, this._propsAnimated.__getAnimatedValue(), this); - if (didUpdate === false) { - this.forceUpdate(); - } + const callback = () => { + setNativeProps(propsAnimatedRef.current.__getAnimatedValue()); }; - this._propsAnimated = new AnimatedProps( - nextProps, - callback, - ); + propsAnimatedRef.current = new AnimatedProps(nextProps, callback); // When you call detach, it removes the element from the parent list // of children. If it goes to 0, then the parent also detaches itself @@ -62,28 +63,39 @@ function createAnimatedComponent(Component: any): any { // this expensive recursive detaching to then re-attach everything on // the very next operation. oldPropsAnimated && oldPropsAnimated.__detach(); - } + }, []); - componentWillReceiveProps(nextProps) { - this.attachProps(nextProps); - } + attachProps(props); - render() { - const { style, ...other} = this._propsAnimated.__getValue(); + // componentWillUnmount-ish + useEffect( + () => () => { + isMountedRef.current = false; + propsAnimatedRef.current && propsAnimatedRef.current.__detach(); + }, + [] + ); + + useImperativeMethods( + ref, + () => ({ + setNativeProps, + getNode: () => componentRef.current, + }), + [] + ); + + const { style, ...other } = propsAnimatedRef.current.__getValue(); + + return ( + + ); + }); - return ( - { this.componentRef = node; }} - /> - ); - } - - getNode() { - return this.componentRef; - } - } AnimatedComponent.propTypes = { style: function(props, propName, componentName) { if (!Component.propTypes) { @@ -103,7 +115,7 @@ function createAnimatedComponent(Component: any): any { // ); // } // } - } + }, }; return AnimatedComponent; diff --git a/yarn.lock b/yarn.lock index e2046c2..484e9a8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1245,7 +1245,7 @@ extsprintf@^1.2.0: version "1.4.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" -fbjs@^0.8.16, fbjs@^0.8.9: +fbjs@^0.8.9: version "0.8.16" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" dependencies: @@ -2024,11 +2024,11 @@ promise@^7.1.1: dependencies: asap "~2.0.3" -prop-types@^15.6.0: - version "15.6.0" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856" +prop-types@^15.6.2: + version "15.6.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" + integrity sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ== dependencies: - fbjs "^0.8.16" loose-envify "^1.3.1" object-assign "^4.1.1" @@ -2095,14 +2095,15 @@ react-deep-force-update@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-1.1.1.tgz#bcd31478027b64b3339f108921ab520b4313dc2c" -react-dom@^16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.2.0.tgz#69003178601c0ca19b709b33a83369fe6124c044" +react-dom@^16.7.0-alpha.0: + version "16.7.0-alpha.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.7.0-alpha.0.tgz#8379158d4c76d63c989f325f45dfa5762582584f" + integrity sha512-/XUn1ldxmoV2B7ov0rWT5LMZaaHMlF9GGLkUsmPRxmWTJwRDOuAPXidSaSlmR/VOhDSI1s+v3+KzFqhhDFJxYA== dependencies: - fbjs "^0.8.16" loose-envify "^1.1.0" object-assign "^4.1.1" - prop-types "^15.6.0" + prop-types "^15.6.2" + scheduler "^0.11.0-alpha.0" react-proxy@^1.1.7: version "1.1.8" @@ -2118,14 +2119,15 @@ react-transform-hmr@^1.0.4: global "^4.3.0" react-proxy "^1.1.7" -react@^16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.2.0.tgz#a31bd2dab89bff65d42134fa187f24d054c273ba" +react@^16.7.0-alpha.0: + version "16.7.0-alpha.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.7.0-alpha.0.tgz#e2ed4abe6f268c9b092a1d1e572953684d1783a9" + integrity sha512-V0za4H01aoAF0SdzahHepvfvzTQ1xxkgMX4z8uKzn+wzZAlVk0IVpleqyxZWluqmdftNedj6fIIZRO/rVYVFvQ== dependencies: - fbjs "^0.8.16" loose-envify "^1.1.0" object-assign "^4.1.1" - prop-types "^15.6.0" + prop-types "^15.6.2" + scheduler "^0.11.0-alpha.0" read-only-stream@^2.0.0: version "2.0.0" @@ -2281,6 +2283,14 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" +scheduler@^0.11.0-alpha.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.11.0.tgz#def1f1bfa6550cc57981a87106e65e8aea41a6b5" + integrity sha512-MAYbBfmiEHxF0W+c4CxMpEqMYK+rYF584VP/qMKSiHM6lTkBKKYOJaDiSILpJHla6hBOsVd6GucPL46o2Uq3sg== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + semver@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"