Prop flow
There are four important things that each component needs to do in order to properly manage the flow of props. What is "flow"? The user invokes your CoolComponent
component with props; the CoolComponent
component creates a Styled
element and gives it props; and the Styled
function invokes your render callback with a new set of props. Whew!
- Pass your component's props to
Styled
. As mentioned above, theStyled
component needs access to the instance props so it can invoke yourdynamicStyle
function correctly. It also incorporates anystyle
orclassName
prop that the user puts on theCoolComponent
into its calculation of the finalclassName
. - Retrieve props from the render callback. Your render callback receives a second parameter with a clean set of props. With one exception (see #4), you should use these props for rendering instead of
this.props
, because the one given to the render callback has been stripped of any styling-related props. Details in #3. - Remove your component's props, and pass a spread to your HTML element. In the render method below, we used a rest property (
...otherProps
) to strip out the props consumed by the component. So, after the stripping in step 2 and the stripping here, what's left inotherProps
? All of the "unknown" props, like data- or aria- attributes, which should be passed down to the HTML element. - If you need
children
, get them fromthis.props
. The render callback will not include children in the props it gives you.
That seems like a lot, but it's really just a lot of explanation to ensure you understand the subtleties. If you treat the component below as a template, there's not much to it.
class TemplateComponent extends React.Component {
render() {
return (
<Styled
name = 'MyComponent'
staticStyle = {staticStyle}
dynamicStyle = {dynamicStyle}
{...this.props}
>
{(className, props) => {
/*
extract component props from the function parameter.
you should do this even for props that are only needed
in your dynamic styling function (i.e., they're not needed
here). that ensures that the spread on the <div> does not
include attributes that aren't recognized by HTML
*/
let {isSelected, isDisabled, ...otherProps} = props;
return (
<div {...otherProps} className = {className}>
{this.props.children}
</div>
);
}}
</Styled>
);
}
}