Skip to content
This repository has been archived by the owner on Aug 19, 2022. It is now read-only.

Add hook and forwardRef support #1027

Merged
merged 11 commits into from
Sep 5, 2019

Conversation

nathanmarks
Copy link
Contributor

@nathanmarks nathanmarks commented Jun 7, 2019

Addresses:
#1016
#1010

This PR makes some big changes, and I understand if dropping support for React < 16.8 on master is not do-able at this time. However, the inability to use hooks and forwardRef with Radium means we are missing out on some of the great features being introduced to React.

Hopefully the changes in here can at least serve as a point for discussion (if everything works as-intended).

  • Requires React v16.8+
  • Supports hooks in radium wrapped components
  • Supports radium wrapped forwardRef components
  • Makes changes to the codepath for function components (see enhancer.js)
  • Uses hooks + new context API internally

I also had to upgrade babel, eslint + plugins, and flow to be able to use the latest version of React features + their associated flow types.

I had to comment out node 6 for appveyor because the eslint react hooks plugin is asking for node 7+

src/enhancer.js Outdated Show resolved Hide resolved
}
}

export function renderFcIntoDocument(element) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Radium (at least on class components) now exports with a HoC to inject context which is written as a function component, and TestUtils.renderIntoDocument requires a class component

const Enhanced = Enhancer(Composed);

const instance = new Enhanced();
const ref = React.createRef();
renderFcIntoDocument(<Enhanced ref={ref} />);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Class components are now wrapped in a HoC for injecting the contexts, so using ref to get access to the instance

const Enhanced = Enhancer(Composed);

const instance = new Enhanced();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't do tests like this as class components are now wrapped in a HoC to inject context

const {radiumConfig} = props;

const configContext = useContext(RadiumConfigContext);
const styleKeeper = useRef<StyleKeeper>(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this won't change if radiumConfig prop changes -- but that is true to the original implementation

src/enhancer.js Outdated
getRadiumStyleState(this)
if (this.props.radiumConfig) {
return (
<RadiumConfigContext.Provider value={this.props.radiumConfig}>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

previous version would override childContext with the config prop if provided

// need to attempt to assign to this.state in case
// super component is setting state on construction,
// otherwise class properties reinitialize to undefined
state: Object = this.state || {};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is due to a change in the class properties behaviour in babel 7.

@kylecesmat
Copy link
Contributor

kylecesmat commented Jun 8, 2019

@nathanmarks major appreciation for this PR - We've been moving towards placing Radium into a more stable maintenance mode and avoiding larger refactors, but this type of work warrants a semver minor release considering the current version of Radium straight up does not support hooks.

We'll work to get this merged and released in 0.26.0

Copy link
Contributor

@kylecesmat kylecesmat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will pull this down and manually verify, changes look really great so far

.babelrc Outdated Show resolved Hide resolved
appveyor.yml Outdated Show resolved Hide resolved
interfaces/inline-style-prefixer.js Show resolved Hide resolved
test/radium-test.js Show resolved Hide resolved
src/style-keeper.js Show resolved Hide resolved
src/enhancer.js Show resolved Hide resolved
@kylecesmat
Copy link
Contributor

Hello @nathanmarks! I wanted to see if there was any assistance I could provide to aide with this pull request :) I have a few spare cycles this week and can help with review or getting the branch ready for merge.

@nathanmarks nathanmarks marked this pull request as ready for review June 17, 2019 14:45
@nathanmarks
Copy link
Contributor Author

nathanmarks commented Jun 17, 2019

@kylecesmat apart from one of the things I highlighted in a comment that needs covering still in the function component enhancer and some additional DRY-ing up between the class and function enhancers, would be great if you could give this a thorough review.

Do you guys have any codebases still running Radium that this could be tested on to validate it? (I noticed you had moved to emotion for some projects, which we are looking into as a long term replacement)

Would be great to make sure we haven't accidentally introduced any issues that aren't covered in the test suite (such as FOUC problems with media queries: #626)

Thanks so much!!

@acusti
Copy link

acusti commented Jun 27, 2019

@nathanmarks Thank you so much for putting this together! I tried out your changes in our app to see how they work with our pretty complex implementation and to make it possible to use hooks in our radium-connected components, and so far so good! To make it easy to test and easy to deploy a version of our app that uses your work, I made a repo with all the built radium files from your branch, which can be directly used as the dependency string with npm/yarn. In the package.json:

-  "radium": "0.25.2",
+  "radium": "brandcast/radium-built#c7bd574",

@ryan-roemer
Copy link
Member

ryan-roemer commented Jun 27, 2019

Thanks @acusti but that shouldn’t actually be necessary. Radium uses the ‘publishr’ ( https://github.com/FormidableLabs/publishr ) tool to to add build deps and a postinstall to actually do a build when installing from git branch, and does none of that when installing from npm/yarn (which has the built, not-in-git dist files).

Did you find something wrong with a direct git branch dependency?

@acusti
Copy link

acusti commented Jun 27, 2019

a postinstall to actually do a build when installing from git branch

That’s clever! I didn’t know, so I just manually ran all the build commands I found in the package.json (build-lib, build-dist, build-es), then copied those built files over into a bare repo (brandcast/radium-built) and committed them, then referred to the commit hash in the dependency string. It works, but using a “direct git branch dependency” sounds way easier. I’ll try this tomorrow:

  "radium": "nathanmarks/radium#add-hook-support",

@acusti
Copy link

acusti commented Jun 27, 2019

@ryan-roemer I tried with the direct git branch dependency and the yarn install failed:

[4/4] 🔨  Building fresh packages...
error /Users/andrew/Projects/next-reference/node/node_modules/radium: Command failed.
Exit code: 1
Command: cd lib || npm run build
Arguments:
Directory: /Users/andrew/Projects/next-reference/node/node_modules/radium
Output:
/bin/sh: line 0: cd: lib: No such file or directory
npm WARN lifecycle The node binary used for scripts is /var/folders/77/wp1tljpd5jn40ghhw7lxl_gr0000gn/T/yarn--1561653493362-0.19655672276763525/node but npm is using /usr/local/bin/node itself. Use the `--scripts-prepend-node-path` option to include the path for the node binary npm was executed with.

> radium@0.25.1 build /Users/andrew/Projects/next-reference/node/node_modules/radium
> npm run clean && builder concurrent --buffer build-lib build-dist build-es

npm WARN lifecycle The node binary used for scripts is /var/folders/77/wp1tljpd5jn40ghhw7lxl_gr0000gn/T/yarn--1561653493362-0.19655672276763525/node but npm is using /usr/local/bin/node itself. Use the `--scripts-prepend-node-path` option to include the path for the node binary npm was executed with.

> radium@0.25.1 clean /Users/andrew/Projects/next-reference/node/node_modules/radium
> rimraf lib es dist

[builder:config:environment] {"cwd":"/Users/andrew/Projects/next-reference/node/node_modules/radium","dir":"/Users/andrew/Projects/next-reference/node/node_modules/builder/lib"}
[builder:config] Unable to load config file: .builderrc
[builder:local-detect] Error importing local builder: Cannot find module '/Users/andrew/Projects/next-reference/node/node_modules/radium/node_modules/builder/bin/builder-core.js'
[builder:local-detect] Using global builder at: /Users/andrew/Projects/next-reference/node/node_modules/builder/bin/builder-core.js
[builder:builder-core:start:52506] Started: concurrent build-lib, build-dist, build-es
[builder:concurrent] build-lib, build-dist, build-es
 * build-lib - builder run --env "{\"BABEL_ENV\":\"commonjs\"}" build-babel -- -d lib --verbose
 * build-dist - builder concurrent --buffer build-dist-dev build-dist-prod
 * build-es - builder run build-babel -- -d es
[builder:concurrent] Starting with queue size: unlimited
[builder:proc:start] Command: builder run --env "{\"BABEL_ENV\":\"commonjs\"}" build-babel -- -d lib --verbose
[builder:proc:start] Command: builder concurrent --buffer build-dist-dev build-dist-prod
[builder:proc:start] Command: builder run build-babel -- -d es
[builder:config:environment] {"cwd":"/Users/andrew/Projects/next-reference/node/node_modules/radium","dir":"/Users/andrew/Projects/next-reference/node/node_modules/builder/lib"}
[builder:config] Unable to load config file: .builderrc
[builder:local-detect] Using global builder at: /Users/andrew/Projects/next-reference/node/node_modules/builder/bin/builder-core.js
[builder:builder-core:start:52508] Started: run build-babel
[builder:local-detect] Error importing local builder: Cannot find module '/Users/andrew/Projects/next-reference/node/node_modules/radium/node_modules/builder/bin/builder-core.js'
[builder:run] build-babel - babel src --ignore "**/__tests__/*","**/__mocks__/*"
[builder:proc:start] Command: babel src --ignore "**/__tests__/*","**/__mocks__/*" -d lib --verbose
{ Error: Cannot find module '@babel/preset-flow' from '/Users/andrew/Projects/next-reference/node/node_modules/radium'
    at Function.module.exports [as sync] (/Users/andrew/Projects/next-reference/node/node_modules/resolve/lib/sync.js:71:15)
    at resolveStandardizedName (/Users/andrew/Projects/next-reference/node/node_modules/@babel/core/lib/config/files/plugins.js:101:31)
    at resolvePreset (/Users/andrew/Projects/next-reference/node/node_modules/@babel/core/lib/config/files/plugins.js:58:10)
    at loadPreset (/Users/andrew/Projects/next-reference/node/node_modules/@babel/core/lib/config/files/plugins.js:77:20)
    at createDescriptor (/Users/andrew/Projects/next-reference/node/node_modules/@babel/core/lib/config/config-descriptors.js:154:9)
    at items.map (/Users/andrew/Projects/next-reference/node/node_modules/@babel/core/lib/config/config-descriptors.js:109:50)
    at Array.map (<anonymous>)
    at createDescriptors (/Users/andrew/Projects/next-reference/node/node_modules/@babel/core/lib/config/config-descriptors.js:109:29)
    at createPresetDescriptors (/Users/andrew/Projects/next-reference/node/node_modules/@babel/core/lib/config/config-descriptors.js:101:10)
    at presets (/Users/andrew/Projects/next-reference/node/node_modules/@babel/core/lib/config/config-descriptors.js:47:19) code: 'MODULE_NOT_FOUND' }
[builder:proc:end:1] Command: babel src --ignore "**/__tests__/*","**/__mocks__/*" -d lib --verbose
[builder:builder-core:end:52508] Task: run build-babel, Error: Command failed: sh -c babel src --ignore "**/__tests__/*","**/__mocks__/*" -d lib --verbose

[builder:proc:end:1] Command: builder run --env "{\"BABEL_ENV\":\"commonjs\"}" build-babel -- -d lib --verbose
[builder:proc:error] Code: 1, Command: builder run --env "{\"BABEL_ENV\":\"commonjs\"}" build-babel -- -d lib --verbose
[builder:config:environment] {"cwd":"/Users/andrew/Projects/next-reference/node/node_modules/radium","dir":"/Users/andrew/Projects/next-reference/node/node_modules/builder/lib"}
[builder:config] Unable to load config file: .builderrc
[builder:local-detect] Using global builder at: /Users/andrew/Projects/next-reference/node/node_modules/builder/bin/builder-core.js
[builder:builder-core:start:52510] Started: run build-babel
[builder:run] build-babel - babel src --ignore "**/__tests__/*","**/__mocks__/*"
[builder:proc:start] Command: babel src --ignore "**/__tests__/*","**/__mocks__/*" -d es
[builder:local-detect] Error importing local builder: Cannot find module '/Users/andrew/Projects/next-reference/node/node_modules/radium/node_modules/builder/bin/builder-core.js'
{ Error: Cannot find module '@babel/preset-flow' from '/Users/andrew/Projects/next-reference/node/node_modules/radium'
    at Function.module.exports [as sync] (/Users/andrew/Projects/next-reference/node/node_modules/resolve/lib/sync.js:71:15)
    at resolveStandardizedName (/Users/andrew/Projects/next-reference/node/node_modules/@babel/core/lib/config/files/plugins.js:101:31)
    at resolvePreset (/Users/andrew/Projects/next-reference/node/node_modules/@babel/core/lib/config/files/plugins.js:58:10)
    at loadPreset (/Users/andrew/Projects/next-reference/node/node_modules/@babel/core/lib/config/files/plugins.js:77:20)
    at createDescriptor (/Users/andrew/Projects/next-reference/node/node_modules/@babel/core/lib/config/config-descriptors.js:154:9)
    at items.map (/Users/andrew/Projects/next-reference/node/node_modules/@babel/core/lib/config/config-descriptors.js:109:50)
    at Array.map (<anonymous>)
    at createDescriptors (/Users/andrew/Projects/next-reference/node/node_modules/@babel/core/lib/config/config-descriptors.js:109:29)
    at createPresetDescriptors (/Users/andrew/Projects/next-reference/node/node_modules/@babel/core/lib/config/config-descriptors.js:101:10)
    at presets (/Users/andrew/Projects/next-reference/node/node_modules/@babel/core/lib/config/config-descriptors.js:47:19) code: 'MODULE_NOT_FOUND' }
[builder:proc:end:1] Command: babel src --ignore "**/__tests__/*","**/__mocks__/*" -d es
[builder:builder-core:end:52510] Task: run build-babel, Error: Command failed: sh -c babel src --ignore "**/__tests__/*","**/__mocks__/*" -d es

[builder:proc:end:1] Command: builder run build-babel -- -d es
[builder:proc:error] Code: 1, Command: builder run build-babel -- -d es
[builder:finish] Hit 2 errors:
  * Error: Command failed: sh -c builder run --env "{\"BABEL_ENV\":\"commonjs\"}" build-babel -- -d lib --verbose

  * Error: Command failed: sh -c builder run build-babel -- -d es

[builder:builder-core:end:52506] Task: concurrent build-lib, build-dist, build-es, Error: Command failed: sh -c builder run --env "{\"BABEL_ENV\":\"commonjs\"}" build-babel -- -d lib --verbose

[builder:config:environment] {"cwd":"/Users/andrew/Projects/next-reference/node/node_modules/radium","dir":"/Users/andrew/Projects/next-reference/node/node_modules/builder/lib"}
[builder:config] Unable to load config file: .builderrc
[builder:local-detect] Using global builder at: /Users/andrew/Projects/next-reference/node/node_modules/builder/bin/builder-core.js
[builder:builder-core:start:52509] Started: concurrent build-dist-dev, build-dist-prod
[builder:concurrent] build-dist-dev, build-dist-prod
 * build-dist-dev - webpack
 * build-dist-prod - webpack --config=webpack.config.minified.js
[builder:concurrent] Starting with queue size: unlimited
[builder:proc:start] Command: webpack
[builder:proc:start] Command: webpack --config=webpack.config.minified.js
[builder:local-detect] Error importing local builder: Cannot find module '/Users/andrew/Projects/next-reference/node/node_modules/radium/node_modules/builder/bin/builder-core.js'
[builder:proc:end:1] Command: builder concurrent --buffer build-dist-dev build-dist-prod
[builder:proc:error] Code: 1, Command: builder concurrent --buffer build-dist-dev build-dist-prod
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! radium@0.25.1 build: `npm run clean && builder concurrent --buffer build-lib build-dist build-es`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the radium@0.25.1 build script.

@ryan-roemer
Copy link
Member

@acusti -- Thanks. I'll take a look.

@ryan-roemer
Copy link
Member

@acusti -- good catch. This PR breaks the publishr workflow.

@nathanmarks -- I'm going to create a patch for you that will hopefully work for our publishr workflow. (package.json changes.)

@ryan-roemer
Copy link
Member

@acusti @nathanmarks -- this should fix the publishr workflow I think!

diff --git a/package.json b/package.json
index 72b92e5..7e04935 100644
--- a/package.json
+++ b/package.json
@@ -61,6 +61,7 @@
     "@babel/plugin-syntax-dynamic-import": "^7.0.0",
     "@babel/plugin-transform-destructuring": "^7.0.0",
     "@babel/preset-env": "^7.0.0",
+    "@babel/preset-flow": "^7.0.0",
     "@babel/preset-react": "^7.0.0",
     "babel-loader": "^8.0.0",
     "builder": "^3.2.3",
@@ -76,9 +77,7 @@
     "react": "^16.8.0"
   },
   "devDependencies": {
-    "@babel/core": "^7.0.0",
     "@babel/node": "^7.0.0",
-    "@babel/preset-flow": "^7.0.0",
     "babel-eslint": "^10.0.1",
     "babel-plugin-istanbul": "^5.1.0",
     "caniuse-api": "^2.0.0",

package.json Outdated Show resolved Hide resolved
},
"devDependencies": {
"babel-eslint": "^7.1.1",
"@babel/core": "^7.0.0",
"@babel/node": "^7.0.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this needed?

package.json Outdated Show resolved Hide resolved
@nathanmarks
Copy link
Contributor Author

@kylecesmat sorry, had a really busy couple of weeks!

Are you guys still wanting to see this get in as the final big update to Radium?

@kylecesmat
Copy link
Contributor

@nathanmarks absolutely no worries, thank you for taking time out of your life to contribute to this project :)

We'd love to include this feature in Radium. I think we're close, let me know if you're able to address the feedback above and we'll get it merged + released.

@acusti
Copy link

acusti commented Aug 27, 2019

@nathanmarks @kylecesmat we (at the company i work for) would also love to see this feature in radium! can we help get it over the finish line? not sure how hard it would be for someone else to get up to speed on everything in this PR, but we might be able to dedicate an engineer to take it over and ship it if that could help.

@nathanmarks
Copy link
Contributor Author

@acusti

Sorry for dragging my feet on this!

Let me see if I can find some time tomorrow or Thursday to address feedback and wrap up my changes. If I don't, I'm happy to work with someone to finish this up!

@nathanmarks
Copy link
Contributor Author

Started to finish up

@nathanmarks nathanmarks changed the title [WIP] Add hook and forwardRef support Add hook and forwardRef support Aug 30, 2019
@coveralls
Copy link

Coverage Status

Coverage decreased (-0.4%) to 94.914% when pulling 775b415 on nathanmarks:add-hook-support into 707cd11 on FormidableLabs:master.

@coveralls
Copy link

coveralls commented Aug 30, 2019

Coverage Status

Coverage decreased (-1.6%) to 93.711% when pulling 7d13188 on nathanmarks:add-hook-support into 4cac024 on FormidableLabs:master.

@acusti
Copy link

acusti commented Aug 30, 2019

@ryan-roemer following up on the publishr workflow, i just retried the nathanmarks/radium#add-hook-support dependency string and it installed successfully, so it seems that is all fixed 👍

@nathanmarks
Copy link
Contributor Author

nathanmarks commented Sep 3, 2019

btw, the coverage report on master is a little messed up 🤔 there's an issue with the line #s after a certain point in most files due to how the webpack rules were configured.

I've fixed this.

This has resulted in a change in coverage for some files that I haven't modified.

For eg:
Master
https://coveralls.io/builds/23873272/source?filename=src/plugins/mouse-up-listener.js

My Build
https://coveralls.io/builds/25499981/source?filename=src/plugins/mouse-up-listener.js

@nathanmarks
Copy link
Contributor Author

@acusti how's the latest working for you? I think everything is done 🤔

@acusti
Copy link

acusti commented Sep 5, 2019

@nathanmarks it’s working great! we put it through QA, found no issues, and are currently using it in production 🚀

@acusti
Copy link

acusti commented Sep 5, 2019

@kylecesmat based on:

@acusti how's the latest working for you? I think everything is done 🤔

sounds like this is ready for a re-review!

@kylecesmat
Copy link
Contributor

@acusti @nathanmarks standby for some code review, will try to get this merged & released today!

@kylecesmat
Copy link
Contributor

Pulled this down and ran the suites/verified publishing. Lets merge this and get it released as v0.26.0

@kylecesmat kylecesmat merged commit b2d9807 into FormidableLabs:master Sep 5, 2019
@nathanmarks nathanmarks deleted the add-hook-support branch September 5, 2019 21:25
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants