Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Adaptations for ReScript 10 / use records with optional fields#769

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
MoOx merged 8 commits intomainfromrescript-10
Oct 12, 2022

Conversation

@cknitt
Copy link
Member

Closes#766.
Wait for ReScript 10 to be released before merging.

Trying to remain compatible as far as possible by keeping (but deprecating) existing creation functions (@obj).

Copy link
Member

@MoOxMoOx left a comment

Choose a reason for hiding this comment

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

Awesome work ! Thanks@cknitt.
I think we could improve styleObj being directly t so we don't even have to use styleObj function but beside this, it's perfect !

@cknitt
Copy link
MemberAuthor

Updated PR for 10.0.0 release version.

@cknittcknitt marked this pull request as ready for reviewSeptember 15, 2022 17:13
* main:  "end" is not a reserved word anymore  0.69.1  Fix 0.69 not compiling on ReScript 10 (#773)  0.69.0  Create HitSlop & Rect module (closes#765)
@cknitt can you check if everything I added is correct (especially for VirtualizedSectionList, not sure if that make sense to change as record...) ? Thanks :)
@MoOx
Copy link
Member

MoOx commentedOct 5, 2022

@cknitt can you check my latest commits please ?

@cknitt
Copy link
MemberAuthor

cknitt commentedOct 5, 2022
edited
Loading

Looks good to me.

ForshareResult andinteractionState there is little benefit in having optional fields, as it is unlikely that the user will ever construct instances of these record types himself. However, they won't hurt either, so I'd say let's go for it to be consistent with the other records definitions.

Copy link
Member

@MoOxMoOx left a comment

Choose a reason for hiding this comment

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

Everything is amazing, but I have concern for Style API changes.

// - transform style
// - shadow style
// - layout style
typestyleObj= {
Copy link
Member

Choose a reason for hiding this comment

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

Just a question here for everyday need:

Now we are supposed to dostyle={Style.styleObj({width: 10.->Style.dp})} instead ofstyle={Style.style(~width=10.->Style.dp,())}. Is there really a direct benefit ? Because with style being styleObj, at the end, we don't save a single char :D
Could we imagine something shorter ? Or maybe directly a record ? I know that array would be an issue but... What if we only accept array as discussed in#632 ? This way, we could only type style={[{width: 10.->dp}]}.
I have to admit that with themed app (light/dark mode) and predefined common styles, I have most of the time use array.

And it would be like React.useState() for example. Original api accepts value or function, but rescript bindings only accept the "most advanced" to avoid bloated api. By using array, we directly allow us to save chars everytime !

Any thoughts ? cc@Freddy03h

Freddy03h reacted with thumbs up emoji
Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Yes, no~ anymore, no() at the end anymore that you can forget, more readable and more familiar to JS developers, definitely a benefit in any case.

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

But it would certainly be nice to be able to avoidStyle.style/Style.styleObj altogether.

Copy link
MemberAuthor

@cknittcknittOct 5, 2022
edited
Loading

Choose a reason for hiding this comment

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

I don't see how it could work in a type-safe manner though, given that nested style arrays are also allowed (and sometimes useful), and that we may also want to keeparrayOption. I think we do need our abstract type (Style.t).

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Maybe we should just make its instead ofstyleObj. Example:

letstyles= {openStyleStyleSheet.create({"playButton":s({display:#flex,alignItems:#center,justifyContent:#center,borderWidth:StyleSheet.hairlineWidth,    }),  })}

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
MemberAuthor

Choose a reason for hiding this comment

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

I will have to remove this then:

@module("react-native") @scope("StyleSheet")externalflatten:array<Style.t>=>Style.t="flatten"

Copy link
Member

Choose a reason for hiding this comment

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

let's break all the things. It's been a while now that StyleSheet.create doesn't returns int anymore but directly styles. It's only validating some values & units.

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Done!

With all these breaking changes I guess we'll need a codemod?

Copy link
Member

Choose a reason for hiding this comment

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

@MoOx I read that it could be back to int (or other value) in react-native-web with the new/next style system

@MoOx
Copy link
Member

MoOx commentedOct 5, 2022

Btw, I think I read somewhere that type record spread is coming, it this a thing ?

* main:  Use polymorphic variant for Platform.os (#771)  Get rid of @string/@int for polyvars (#770)
@cknitt
Copy link
MemberAuthor

Yeah, I pinged you inrescript-lang/rescript#5659. 😄

There is a PoC now:rescript-lang/rescript#5715

MoOx reacted with thumbs up emoji

MoOx
MoOx previously approved these changesOct 7, 2022
Copy link
Member

@MoOxMoOx left a comment

Choose a reason for hiding this comment

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

I guess a codemode would be nice but I don't feel confortable handling it. Never did one and don't have much time right now.
But what if?...
We temporarily keep array, arrayOption & style functions (but deprecate them) and adjust their result... since RN handle nested array !?

  • style() could return a array (here we use external + a tiny function ?)
  • array/arrayOption could accepts array & return styles too ?

This could work and would avoid people a major breaking change ? Am I missing a thing ?

switchstyle {
|Some(style)=>style
|None=>empty
}
Copy link
Member

Choose a reason for hiding this comment

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

Can't we use identity to do option => t ?

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

No, becauset is a record type now, butNone is not a record.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah I get that. I was just thinking that RN styles accepts undefined, null & falsy values...

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Yeah but the user may do

letx=Style.optional(None)letcolor=x.color// 💥 runtime exception

Copy link
Member

Choose a reason for hiding this comment

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

Yeah right, without abstract type, that's mandatory :)

@module("react-native") @scope("StyleSheet")
externalcreate:Js.t<'a>=>Js.t<'a>="create"
@module("react-native") @scope("StyleSheet")
externalflatten:array<Style.t>=>Style.t="flatten"
Copy link
Member

Choose a reason for hiding this comment

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

I am wondering if this can still work per RN docs. It's supposed to handle exactly this: flatten an array. Since we type styles != type t, this could still work right ?

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Ah, I think you are right, I was confusing it with "%identity", this should still work as it is. So I can add it back.

But you won't be able to directly pass the result directly to a view's style prop anymore (as that expects an array now).

@cknitt
Copy link
MemberAuthor

cknitt commentedOct 7, 2022
edited
Loading

I guess a codemode would be nice but I don't feel confortable handling it. Never did one and don't have much time right now. But what if?... We temporarily keep array, arrayOption & style functions (but deprecate them) and adjust their result... since RN handle nested array !?

  • style() could return a array (here we use external + a tiny function ?)
  • array/arrayOption could accepts array & return styles too ?

This could work and would avoid people a major breaking change ? Am I missing a thing ?

What we can do is haveStyle.style(),Style.viewStyle() etc. returnStyle.styles =Style.array<Style.t> as you suggested. This can then be passed to a view's style prop as before.

But

externalarray:array<styles>=>styles="%identity"externalarrayOption:array<option<styles>>=>styles="%identity"

is equivalent to

externalarray:array<array<Style.t>>=>array<Style.t>="%identity"externalarrayOption:array<option<array<Style.t>>>=>array<Style.t>="%identity"

which are not correctly typed. This was ok with an abstract type as a result, but is not correct anymore now.
I it will work though, as long as the user only uses the resulting value to pass it to a view's style prop.

@MoOx
Copy link
Member

MoOx commentedOct 7, 2022

For array & arrayOption, we could turn them into a function instead of external ?

@cknitt
Copy link
MemberAuthor

Yes, but this has performance implications.

@MoOx
Copy link
Member

MoOx commentedOct 7, 2022

The idea is still to have them deprecated. Do you think that's a bad idea to make them ?

@cknitt
Copy link
MemberAuthor

No, I can do that. 👍

@cknitt
Copy link
MemberAuthor

BTW, I am wondering about the general performance implications of passing an array instead of a style object now.

The style object would usually be created once (StyleSheet.create) and then always the same instance would be passed. When wrapping it in an array, this will be a new array instance every time.

@MoOx
Copy link
Member

MoOx commentedOct 7, 2022

That's right. I never measured this. I use array everywhere but never thought about it.@Freddy03h are you doing the same, array inside jsx or do you compute them first ?

I generally care about perfs when I "feel" that there is an issue, but having this everywhere could have an impact but I have no clue if that could be feel by the end user or not 😁

@cknitt
Copy link
MemberAuthor

So this will run for every style unnecessarily passed within an array:

https://github.com/facebook/react-native/blob/73bcedb903c330fddca1cab40bc501cc073a4872/Libraries/StyleSheet/flattenStyle.js#L28

We are really moving away from the zero cost idea here, I am getting second thoughts again. 😞

@MoOx
Copy link
Member

MoOx commentedOct 7, 2022

In practise for me this won't change a thing as I use array almost everywhere.
But I totally get your point.
Assuming that's a thing, can we measure this ? If you have a complex screen with, let's say, hundreds of style declaration that have a single item, what is the impactper render in terms for performances ? Is this >1ms, >10ms, >100ms ?

@Freddy03h
Copy link
Member

I don't think it will be a performance issue.

But… I'm thinking… array was just a convenient way of merging style prop, in a time spread syntax wasn't easily usable

There is no difference between these in js :

style={[style,styleFromProp,{paddingTop:insets.top}]}style={{ ...style, ...styleFromProp, ...{paddingTop:insets.top}}}

So it could be possible to completely ditch the array!

For now it's not seems to be possible with rescript record…
But the error isn't relevant anymore since optionnal fields :

Records can only have one... spread, at the beginning.
Explanation: since records have a known, fixed shape, a spread like{a, ...b} wouldn't make sense, asb would override every field ofa anyway.

@MoOx
Copy link
Member

MoOx commentedOct 7, 2022

@Freddy03h using array or object is imo approximately the same result: on every render, you "change" styles.
Compared to using a stylesheet (which create a "static" object) where you never change the style prop.

This don't work for dynamic styles as you always have to "get" the theme or dynamic base from somewhere in your app.

In short: for people like you and me, approximately no diff.
For people using StyleSheet.create only: maybe a change on runtime, but should be measured... If you don't re-render a lot, probably a tiny change.

@Freddy03h
Copy link
Member

Freddy03h commentedOct 7, 2022
edited
Loading

@MoOx It's also possible to open a PR on react-native to optimize flattenStyle for an array of 1 if we found perf issue

But what are you thinking about ditching the array?

@cknitt
Copy link
MemberAuthor

@Freddy03h Actually ditching the array and just spreading would be nice, but the language support is not there yet.

Also, you wrote:

I read that it could be back to int (or other value) in react-native-web with the new/next style system

If that's the case, then the style values won't be records and the spreading is not going to work.

Freddy03h reacted with thumbs up emoji

@Freddy03h
Copy link
Member

Freddy03h commentedOct 7, 2022
edited
Loading

😅

For the performance issue: to keep an usable app on low end device with Android 6, you need to memoize your components if there is too much rerenders.
So, I think the problem with flattenArray would be an issue only if there is too many re-render of your component, and in these case you would need to memoize it anyway.

@cknitt
Copy link
MemberAuthor

@MoOx@Freddy03h I have given this more thought over the weekend.

There are various third party libs out there for rescript-react-native. If we changeStyle.t to be a record and all style props to acceptStyle.styles = array<Style.t> instead ofStyle.t like in my last commit, then all such libs would have to adapt to that, too. I think that would be too much breakage, and we should stay withStyle.t being the type used by the style props.

For me there are still too many uncertainties / moving parts here. Some concerns may be mitigated later though (when extensible records are available in ReScript so that components from third party libs can inherit their base props from components in rescript-react-native). Not so sure about others, like react-native-web maybe using ints for styles.

For now, I would propose to finish this PR without the change to arrays for style props, i.e. still keeping Style.t abstract as it is now, and continue the discussions about arrays for style props in a separate issue.

I would simplify things though so that there is a single type for style records (not viewStyleObj, textStyleObj etc.) and that it is used like I described above (with justs instead ofstyle):

letstyles= {openStyleStyleSheet.create({"playButton":s({display:#flex,alignItems:#center,justifyContent:#center,borderWidth:StyleSheet.hairlineWidth,    }),  })}

And people can still use the existing style() function as an alternative.

BTW, I was also thinking that maybe we should not deprecate the old creation functions yet, but wait for that until a later release to give users some time to transition.

@cknitt
Copy link
MemberAuthor

@MoOx Updated the PR as described. Can we get it merged and continue discussing/evaluating the array style props ideas elsewhere?

Copy link
Member

@MoOxMoOx left a comment

Choose a reason for hiding this comment

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

Yeah looks good. You are right that this need some thoughts.

@MoOxMoOx merged commite606a03 intomainOct 12, 2022
@MoOxMoOx deleted the rescript-10 branchOctober 12, 2022 07:30
@cknittcknitt mentioned this pull requestOct 21, 2022
5 tasks
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@Freddy03hFreddy03hFreddy03h left review comments

@MoOxMoOxMoOx approved these changes

Assignees

No one assigned

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ReScript 10 / records with optional fields

4 participants

@cknitt@MoOx@Freddy03h

[8]ページ先頭

©2009-2025 Movatter.jp