In my opinion describing presentation components with simple props is more readable. For example:
// :)
<Button blue big />
// :/
<Button color="blue" size="big" />
I agree that setting things as key=value
allow us to validate them or set up default values, like:
Button.propTypes = {
color: React.PropTypes.oneOf(['blue', 'red', 'green']),
size: React.PropTypes.oneOf(['small', 'medium', 'big']),
};
Button.defaultProps = {
color: 'blue',
size: 'medium',
};
//...
<Button color="blue" size="big" />
But I still like <Button big red />
:)
So I was thinking how to do it. Let's say we have our Button
component and we want to control size
and color
props.
So we can define two maps:
const fontSizes = {
small: 10,
medium: 15,
big: 20,
};
const colors = {
blue: 'blue',
red: 'red',
green: 'green',
};
Keep in mind that you can store those maps in separated modules and access them anywhere.
Now let's write out styled Button
component:
const Button = styled.button`
padding: 10px;
border: 1px solid #eee;
background-color: ${???};
border-radius: 3px;
font-size: ${???}px;
`;
Cool! Now we want to define both background-color
and font-size
for two cases:
- Property is defined.
- Property is not defined so:
- We have some default value.
- We just pass.
First idea:
background-color ${any(colors, 'white')}
So we provide map and default key. I know any is not the best idea :) Here it is:
const any = (map, fallback) => ((props) => {
const keyFromProps = Object.keys(map).find(key => props[key]);
return map[keyFromProps || fallback];
});
This function will search for first existing key in map (for example colors
). When no key was found fallback key will be used.
But there is a problem. Default value is set inside styles definition (this white
word).
So second version:
font-size: ${any2(fontSizes, 'size')}px;
const any2 = (map, fallback) => ((props) => {
const keyFromProps = Object.keys(map).find(key => props[key]);
return map[keyFromProps || props[fallback]];
});
Looks almost the same ;) But now second argument is name of the prop that will provide default value. So now you can have something like:
Button.defaultProps = {
size: 'big',
};
//...
any2(fontSizes, 'size')
The cool thing is that you can now have:
<Button small blue />
// and
<Button size="small" color="blue" />
What you think? Is there any better way to do this?