Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[react-jss] Add flow typings #818

Merged
merged 27 commits into from
Aug 15, 2018

Conversation

gomesalexandre
Copy link
Contributor

This is a work-in-progress PR, this first commit is pretty much just the work done before the switch to monorepo.

TODO:

  • 100% flow coverage for react-jss
  • adding script for copying source files

package.json Outdated
@@ -99,5 +99,8 @@
"sinon": "4.5.0",
"webpack": "^2.3.3",
"zen-observable": "^0.6.0"
},
"dependencies": {
"flow-copy-source": "^2.0.2"
Copy link
Member

Choose a reason for hiding this comment

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

We don't copy the source files. We already do the step to use flow typings.

Copy link
Contributor Author

@gomesalexandre gomesalexandre Aug 8, 2018

Choose a reason for hiding this comment

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

Fair enough, I didn't see the babel-plugin-transform-flow-strip-types babel plugin, removed

@@ -0,0 +1,11 @@
[ignore]
Copy link
Member

Choose a reason for hiding this comment

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

This file shouldn't exist because there is a flow config in the root for all packages

@@ -33,7 +33,8 @@
"decorator"
],
"scripts": {
"prepare": "node ../../scripts/prepare.js"
"prepare": "node ../../scripts/prepare.js",
"flow": "flow"
Copy link
Member

Choose a reason for hiding this comment

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

Again, we don't need to run flow here as it's being run from the root directory

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed

const getStyles = (stylesOrCreator, theme) => {
type Props = {
classes: ?{},
innerRef?: () => {},
Copy link
Member

Choose a reason for hiding this comment

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

should be (comp: ComponentType<{}> | null) => void. You could make the component type more exact with moving the props into the generic types of createHOC

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Used (comp: ComponentType<{}> | null) => void in the current implementation, will implement generics in the next PR, it's still a bit of overhead for me still

// We remove previous dynamicSheet only after new one was created to avoid FOUC.
if (prevState.dynamicSheet !== this.state.dynamicSheet && prevState.dynamicSheet) {
Copy link
Member

Choose a reason for hiding this comment

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

&& prevState.dynamicSheet should not be removed!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same diff reason, fixed

RuleOptions,
JssStyle
} from 'jss/lib/types'
import RuleList from 'jss/lib/RuleList'
Copy link
Member

Choose a reason for hiding this comment

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

should be imported from jss as a type

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

ToCssOptions,
RuleOptions,
JssStyle
} from 'jss/lib/types'
Copy link
Member

Choose a reason for hiding this comment

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

All of those should be imported from jss

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

import RuleList from 'jss/lib/RuleList'
import {create} from '../jss'

export interface JssSheet {
Copy link
Member

Choose a reason for hiding this comment

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

No need to redefine the StyleSheet here. Just import it from jss as a type

themeListener: any => any
},
inject?: Array<'classes' | 'themes' | 'sheet'>,
jss?: create,
Copy link
Member

Choose a reason for hiding this comment

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

Should be a Jss instance and not a function which creates an instance

const sheet = dynamicSheet || staticSheet
// $FlowFixMe defaultProps are not defined in React$Component
const defaultClasses = InnerComponent.defaultProps ? InnerComponent.defaultProps.classes : {}
const classes = {...defaultClasses, ...sheet.classes, ...userClasses}

Copy link
Member

Choose a reason for hiding this comment

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

Why did you change the logic of this code?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For now this is essentially a copy and paste from previous PR. Given the diff shows there are some changes (such as this one) that haven't been integrated in it, I'll take care of it top-priority, before working on anything else

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reverted

@HenriBeck
Copy link
Member

Also please add typings for the other files when you have time. Especially for the JssProvider

getDynamicStyles(styles)
)
staticSheet[dynamicStylesNs] = dynamicStyles
} else dynamicStyles = staticSheet[dynamicStylesNs]
Copy link
Member

Choose a reason for hiding this comment

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

Again, no logic changes here please

stylesOrCreator: StylesOrThemer,
InnerComponent: ComponentType<P>,
options: Options = {}
): ComponentType<any> {
Copy link
Member

Choose a reason for hiding this comment

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

The returning component props should be typed exactly

@@ -1,3 +1,5 @@
// @flow
type Classes = {[string]: string}
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

@@ -0,0 +1,19 @@
// @flow
import type {StyleSheetOptions} from 'jss'
import jss from '../jss'
Copy link
Member

Choose a reason for hiding this comment

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

Import the Jss type also from jss

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

export type Styles = {[string]: {}}
export type ThemerFn = (theme: Theme) => Styles
export type StylesOrThemer = Styles | ThemerFn
export type Classes<S> = {|
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

@HenriBeck
Copy link
Member

Quick guideline on which props the HOC should accept:

  • All of the props of the injected Component
  • An additional innerRef prop which needs to be a function with the injected Component as an argument

I don't think we need to use the $Diff operator for props like classes because the user is actually allowed to overwrite those props.

@gomesalexandre
Copy link
Contributor Author

@HenriBeck Do we really need to init options to empty object literal {} if not passed to createHOC? It produces a bit of flow errors because of l.85 i.e
const {theming = defaultTheming, inject, jss: optionsJss, ...sheetOptions} = options.

Then of course, accessing a property of undefined options object with no default would produce errors but that could be mitigated.

@gomesalexandre
Copy link
Contributor Author

gomesalexandre commented Aug 9, 2018

@HenriBeck Regarding the HOC, the returned component is stripped of the classes prop isn't it ? That's the logic behing the use of the $Diff util here. But in that case I can simply use an intersection type instead of a Diff type

@HenriBeck
Copy link
Member

No, I was wrong about that before, see https://github.com/cssinjs/jss/blob/master/packages/react-jss/src/createHoc.js#L191

User classes override the from the stylesheet.

.eslintrc Outdated
@@ -4,7 +4,8 @@
"rules": {
"import/no-unresolved": 0,
"flowtype/define-flow-type": 1,
"flowtype/use-flow-type": 1
"flowtype/use-flow-type": 1,
"semi": ["error", "never"]
Copy link
Member

Choose a reason for hiding this comment

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

Should we use spaces instead of tabs?

Copy link
Member

Choose a reason for hiding this comment

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

I think this can be reverted anyway because prettier takes care of it. I actually write the code with semicolons and prettier removes them for me

Copy link
Member

Choose a reason for hiding this comment

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

But yes, definetly spaces

Copy link
Contributor Author

@gomesalexandre gomesalexandre Aug 10, 2018

Choose a reason for hiding this comment

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

Using the indent rule would avoid such issue, I have automatic linting fixes on save in VSCode. Plus we would get errors thrown within the hook, should I add it ?

Copy link
Member

Choose a reason for hiding this comment

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

We also run prettier in the precommit git hook so it's unnecessary

@HenriBeck HenriBeck requested a review from kof August 12, 2018 16:00
@HenriBeck
Copy link
Member

@kof types should be done

@HenriBeck HenriBeck changed the title WIP PR: Add react-jss flow typings [react-jss] Add flow typings Aug 14, 2018
@@ -57,41 +74,49 @@ let managersCounter = 0
/**
* Wrap a Component into a JSS Container Component.
*
* IProps: Props of the InnerComponent.
* OProps: The Outer props the HOC accepts.
*
* @param {Object|Function} stylesOrCreator
Copy link
Member

Choose a reason for hiding this comment

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

I think we can remove those jsdoc comments now

Copy link
Member

Choose a reason for hiding this comment

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

Will do some cleanup in another PR. Have some small fixes etc. in mind

@@ -57,41 +74,49 @@ let managersCounter = 0
/**
* Wrap a Component into a JSS Container Component.
*
* IProps: Props of the InnerComponent.
Copy link
Member

Choose a reason for hiding this comment

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

InnerProps would be probably a better name, no?

Copy link
Member

Choose a reason for hiding this comment

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

already using InnerProps though, that's why I had to name it IProps 🤔

Copy link
Member

Choose a reason for hiding this comment

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

lets find a better convention, maybe InnerPropsType?

import PropTypes from 'prop-types'
import type {Jss, generateClassName as GenerateClassNameType, SheetsRegistry} from 'jss'
Copy link
Member

Choose a reason for hiding this comment

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

why mapping from lower case to capital?

Copy link
Member

Choose a reason for hiding this comment

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

ohh, I think we need to rename it to upper case in the core package in the first place

Copy link
Member

Choose a reason for hiding this comment

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

Once it starts uppercase you don't need to add Type suffix either

@HenriBeck HenriBeck merged commit 1e9ba74 into cssinjs:master Aug 15, 2018
@@ -176,6 +209,7 @@ export default (stylesOrCreator, InnerComponent, options = {}) => {
})
}

// $FlowFixMe InnerComponent can be class or stateless, the latter doesn't have a defaultProps property
Copy link
Member

Choose a reason for hiding this comment

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

it may have defaultProps property same way as class based

Copy link
Member

@HenriBeck HenriBeck Aug 15, 2018

Choose a reason for hiding this comment

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

yeah but flow doesn't have defaultProps typed on the class nor the functional component https://github.com/facebook/flow/blob/master/lib/react.js#L99

Copy link
Member

Choose a reason for hiding this comment

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

weird, we should look for an issue there for explanation or raise one .... really weird

Copy link
Member

Choose a reason for hiding this comment

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

The explanation is in the comment above.

Copy link
Member

Choose a reason for hiding this comment

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

lol ... my day is over :)

b768b78919504fba9de2c03545c5cd3a?: {[key: number]: SheetsManager},
'6fc570d6bd61383819d0f9e7407c452d': StyleSheetFactoryOptions & {disableStylesGeneration?: boolean}
}
export type OuterProps<IP, C> = IP & {innerRef: (instance: ElementRef<C> | null) => void}
Copy link
Member

Choose a reason for hiding this comment

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

Lets not use these abbreviations, they are hard to understand

export type OuterProps<IP, C> = IP & {innerRef: (instance: ElementRef<C> | null) => void}
export type Styles = {[string]: {}}
export type ThemerFn = (theme: Theme) => Styles
export type StylesOrThemer = Styles | ThemerFn
Copy link
Member

Choose a reason for hiding this comment

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

ThemerFn -> ThemeCreator

Copy link
Member

Choose a reason for hiding this comment

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

ThemeCreator seems a little bit misleading

Copy link
Member

Choose a reason for hiding this comment

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

Maybe StylesCreator?

Copy link
Member

Choose a reason for hiding this comment

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

my bad, yes StylesCreator

bhupinderbola pushed a commit to bhupinderbola/jss that referenced this pull request Sep 17, 2019
* First commit

* Fixes on createHOC and injectSheet

* More fixes on createHOC and injectSheet

* Better flow typings on createHOC

* Moved types/index.js just to types.js and added InnerProps and OuterProps utility types

* Simplified typings of injectSheet.js

* Updated and fixed some typings in createHOC.js

- Used OuterProps and InnerProps types
- Fixed the props of the returning component

* Removed unnecessary types in ns.js

* Added flow flag to some untyped files

* Exporting StyleSheetFactoryOptions now instead of StyleSheetOptions

* Fix typing of getDisplayName

* Added Context Type and updated Options to use StyleSheetFactoryOptions type

* Moved types/index.js just to types.js and added

* Improved Context Type

* Updated createHoc to use Context type

* Improved typing of the Theming option

* Formatted code with prettier

* Updated size snapshot and lockfile

* Make options in injectSheet optional an default it to an empty object

* Fixed types of the JssProvider props
- Made most props optional
- Only allow one child

* Remove semi eslint rule

* Removed unnecessary types

* Remove unnecessary check

* Updated a if statement and fixed removing dynamic sheet from global registry after component unmounts

* Fixed naming of some type names to always start with an uppercase char

* Renamed generic types of createHOC
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants