-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
shouldForwardProp support #3006
shouldForwardProp support #3006
Conversation
Code now re-worked a bit and rebased on current master |
4072f9d
to
1cbf75a
Compare
This comment has been minimized.
This comment has been minimized.
Does this support statically forwarding the In other words, will a component as defined below pass the const Comp = styled(AnotherStyledComponent).withConfig({
shouldForwardProp: prop => ['as'].includes(prop)
})`
/* ... */
`; |
@diondiondion what would a unit test look like for that? Something like this? it('supports statically forwarding the as prop', () => {
const StyledDiv = styled('div')`
color: red;
`;
const StyledDiv2 = styled('div')`
color: blue;
`;
const ComposedDiv = styled(StyledDiv).withConfig({
shouldForwardProp: prop => !['as'].includes(prop)
})`
/* ... */
`;
const wrapper = TestRenderer.create(<ComposedDiv as={StyledDiv2} />);
const { props } = wrapper.root.findByType('div');
// expect ?
}); |
@diondiondion good question - and to be honest, I'm not sure. I did wrote some tests concerning how |
Fwiw we would not deprecate forwardedAs so might not be an issue
…On Fri, Feb 7, 2020 at 11:26 AM Steve Sims ***@***.***> wrote:
@diondiondion <https://github.com/diondiondion> good question - and to be
honest, I'm not sure. I did wrote some tests concerning how as works, but
I'm not entirely sure they cover what you're asking about. Unfortunately I
don't have the time to check on this right now, and won't until Monday at
the earliest.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#3006?email_source=notifications&email_token=AAELFVU25JC5GJ226KFYSX3RBWDR5A5CNFSM4KROUCCKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOELDT3NQ#issuecomment-583482806>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAELFVVBLE7FFGSC6FUDTT3RBWDR5ANCNFSM4KROUCCA>
.
|
I realise now that the example in my previous question had a typo in it, it was set up to prevent the
@penx Let's use an intermediate JSX component as an example as that's the most likely real world use case I can think of. it('supports statically forwarding the as prop', () => {
const Clickable = styled('a')`
background-color: pink;
`;
const Button = ({as, className, children}) => (
<Clickable as={as} className={className}>Hello {children}</Clickable>
);
const MenuButton = styled(Button).withConfig({
shouldForwardProp: prop => prop === 'as'
})`
margin-right: 4px;
`;
const wrapper = TestRenderer.create(<MenuButton as="button">world</MenuButton>);
}); Given this example, I'd expect The rendered component's
@probablyup In my mind However, the scenario where you have to use it instead of the |
We’re not making subtractive API changes at this point so we can
re-evaluate at a later date
…On Sat, Feb 8, 2020 at 11:18 AM diondiondion ***@***.***> wrote:
I realise now that the example in my previous question had a typo in it,
it was set up to *prevent* the as prop from being passed on. I've edited
it now.
what would a unit test look like for that? Something like this?
@penx <https://github.com/penx> Let's use an intermediate JSX component
as an example as that's the most likely real world use case I can think of.
it('supports statically forwarding the as prop', () => {
const Clickable = styled('a')`
background-color: pink;
`;
const Button = ({as, className, children}) => (
<Clickable as={as} className={className}>Hello {children}</Clickable>
);
const MenuButton = styled(Button).withConfig({
shouldForwardProp: prop => prop === 'as'
})`
margin-right: 4px;
`;
const wrapper = TestRenderer.create(<MenuButton as="button">world</MenuButton>);
});
Given this example, I'd expect The rendered component's
- element type to be "button"
- text content to equal "Hello world"
- styles to be background-color: pink; margin-right: 4px;
Fwiw we would not deprecate forwardedAs so might not be an issue
@probablyup <https://github.com/probablyup> In my mind forwardedAs has
one valid use case – when it's used at the same time as the as prop.
However, the scenario where you *have* to use it *instead of* the as prop
because not doing so would break the component or its styles is why I'm
advocating for it. In those cases, forwarding the as prop statically
would be a MUCH safer option. The lack of this ability creates inconsistent
component APIs that unnecessarily require knowing the internals of a
component.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#3006?email_source=notifications&email_token=AAELFVWK5GDRPLKLA7YEFATRB3LN5A5CNFSM4KROUCCKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOELFVNWQ#issuecomment-583751386>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAELFVWBTOHV53B7CGJR3CDRB3LN5ANCNFSM4KROUCCA>
.
|
Not sure how this is a "subtractive API change", but alright. But wouldn't not introducing this capability from the get go make adding it later a potential breaking change? It seems like that's how it should work. |
This comment has been minimized.
This comment has been minimized.
@@ -180,6 +192,20 @@ function useStyledComponentImpl<Config: {}, Instance>( | |||
return createElement(elementToBeCreated, propsForElement); | |||
} | |||
|
|||
function getShouldForwardProp(options, target, isTargetStyledComp) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Let's maybe keep this inlined next to finalAttrs
for the sake of having them all in one place. I'd argue we can clean this up in a separate refactor PR and get rid of some of the legacy stuff in this file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
@@ -75,6 +75,7 @@ interface StyledComponentWrapperProperties { | |||
displayName: string; | |||
foldedComponentIds: Array<string>; | |||
target: Target; | |||
shouldForwardProp: Function; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can introduce a type for this, since it's just (prop: string) => boolean
let's also remember that this is optional and may be undefined
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
// i.e. Don't pass through non HTML tags through to HTML elements | ||
// else (we're on a component - pass through all by default) | ||
// () => true | ||
const shouldReallyForwardProp = shouldForwardProp || ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the comment here is redundant if this was a little clearer in the first place 😅
If we do a little refactor we can clean this up and make what's going on a lot clearer.
shouldFilterProps
could be reverted and we can removeisTargetTag
from it.- then wee can introduce a separate variable:
const propFilterFn = shouldForwardProp || (isTargetTag && validAttr);
. if (shouldFilterProps)
becomesif (shouldFilterProps || propFilterFn)
- Then
shouldReallyForwardProp(key)
(which btw has unnecessary parens) can be replaced by:(!propFilterFn || propFilterFn(key))
- lastly we can now rename
shouldFilterProps
toshouldFilterComputedProps
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done - was a little bit more involved, but essentially followed your suggestions - also didn't rename shouldFilterProps
cos that didn't feel entirely worth it 😁
return target.shouldForwardProp; | ||
} | ||
|
||
return options.shouldForwardProp; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@probablyup This can probably be done separately but we can totally add shouldForwardProp
as a shortcut to replace the manual withConfig
, right? Just to have alignment with Emotion.
I'd also argue now that we're touching filtering props, "transient props" (props that are always filtered) could also be revived after merging this. (Ref: #2093)
adds support for use of `shouldForwardProp` config method, which can be used to explicitly determine which props should be forwarded on if this config is not provided then existing functionality is preserved (i.e. all props passed to components, or for HTML elements check using `validAttr`) Inspired by the same feature in emotion
following feedback from @kitten, `shouldForwardProp` now has a proper flow-type definition refactor how `shouldForwardProp` is used to make code slightly clearer code to compose `shouldForwardProp` now in-lined into `createStyledCompontent`
1cbf75a
to
94b2d76
Compare
// $FlowFixMe | ||
shouldForwardProp = prop => target.shouldForwardProp(prop) && options.shouldForwardProp(prop); | ||
} | ||
({ shouldForwardProp } = target); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn’t seem right maybe, 🤔 was this supposed to be in an else
statement?
nit: Also can we drop the destructuring here please? We’re also not destructuring for the arrow function composition above, so let’s maybe settle on one pattern for both?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
heh - i didn't want to use destructuring here - eslint complained at me 😉 happy to drop
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and yes - should have had an else
in there - good spot 😁
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking amazing! 👏 thanks for the time to submit this and to get it updated
Once we’ve got this merged I hope we can internally discuss and move on to add a shortcut replacing the manual usage of withConfig
. I hope to be able to merge this later today 🍀
Hi there do you have any timeline when this will be released? |
@diondiondion FYI i've not been ignoring your question, and have looked into it quite deeply. There's an issue with the test that you've proposed:
The problem is that by providing an Without using It seems to me that the current |
@stevesims No worries, thanks for looking into it.
Yes, but that's exactly the point of my request. I want to be able to tell styled-components that The
Isn't every prop passed to the |
Any updates on when this will be released? |
I feel with @Steveeeie. Any plans on this being released soon? |
Ppppplllleeease can we merge this? i was about to start migrating to Emotion for this very reason but already started missing the feel of s-c. |
I've been hoping for this feature to be implemented for so long, would absolutely love to see it merged! Thanks for all the work on this. |
@kitten sorry for ping but we have a lot of excited people here. Anything we could do to help get it merged? Docs need to be written or anything? |
@lucastobrazil Yes a PR for the website to add this API documentation would be great. I think this is ready to be merged though. Someone will also need to work on the typing implementations for TS and Flow. |
We also need a PR for |
Ohhhh yes! So so so happy about this. Thank you everyone for your work <3 |
Just trying this out locally - based on the tests written, i've tried doing this: const Box = styled.div.withConfig({
shouldForwardProp: prop => !['font-family'].includes(prop)
})(
{ boxSizing: 'border-box' },
compose(
space,
// ...
)
); But it doesn't seem to call the |
I'm facing the same issue as @lucastobrazil. Is it something we are missing? |
@Martinnord I managed to get it working with the local styled components sandbox app that is bundled with the mono repo. Following the example in the test it worked. Was trying to use Do we have any visibility into the release plan for the next official npm release with this feature in it? |
@probablyup Are you able to give an update as to when this will be part of a release? |
Near future. There’s an SSR bug I’m looking to resolve before cutting 5.1
…On Mon, Mar 16, 2020 at 8:55 AM Steve Meredith ***@***.***> wrote:
@probablyup <https://github.com/probablyup> Are you able to give an
update as to when this will be part of a release?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#3006 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAELFVQNZ3CAT4LPUK3IYD3RHYOTBANCNFSM4KROUCCA>
.
|
Near future meaning? Rebuilding a component library with Styled System and this is my biggest hang up at the moment. |
@probablyup can we get an update on when this will be released? |
@probablyup anything we can do to help? seems like a lot of folks are waiting for this and would probs be happy to assist :) |
I was waiting on #3061 but I think I'll just cut a release later tonight since it's taking a while. |
Yeah sorry I wouldn't wait on that, need to figure out what the hell is going on before I can submit a fix, and since it is a fix we can cut a patch when it's ready. |
Great team effort everyone 👏 |
Out in 5.1, thanks everyone for pitching in! https://github.com/styled-components/styled-components/releases/tag/v5.1.0 |
Discussion of typings for this new feature: DefinitelyTyped/DefinitelyTyped#43693 |
Following discussion elsewhere, such as on #2780, re-opening this PR (previously #2392)
adds support for use of
shouldForwardProp
config method, which can be used to explicitly determine which props should be forwarded onif this config is not provided then existing functionality is preserved (i.e. all props passed to components, or for HTML elements check using
validAttr
)Inspired by the same feature in emotion
Resolve #439
Resolve #2878