Receive component props in decorator
Andreyco opened this issue · comments
Receive props passed to component in decorator function in order to create style definition.
Example:
function Avatar({ styles }) {
return <Image style={styles.image} />
}
const AvatarWithStyle = withStyles(({ color }, ownProps) => ({
image: {
width: ownProps.imageSize,
height: ownProps.imageSize,
borderRadius: ownProps.imageSize / 2,
},
}))(Avatar);
Will pay more attention later in order to discover whether it's possible with existing implementation.
While this would be convenient, I'm not sure this is a great idea for performance. If you are working with a style that has high-cardinality, it is probably a bad choice to put that through withStyles
. And low-cardinality styles can be specified pretty easily in the standard way ({...css(isFoo && styles.foo)}
). By keeping props out of this function, the API and usage is clear and consistent.
As I looked into the code, performance related issue come up. I must agree with you - cons of this approach surpass its pros.
I am searching for a solution to set the backgroundImage using a url from props.
It's not possible to define all the possible images inside the withStyles hoc because file names are updated each build. Therefore I cannot use ({...css(imageFoo && styles.imageFoo, imageBaz && styles.imageBaz)})
Any suggestions?
Put the filenames in a JSON file, under hardcoded key names, recompute it every build, import the JSON file in the file?
I didn't mention that the data set will grow over time so the solution should scale and work with variable image url's.
It'd take a pretty massive data set for that solution to not work. Regardless, hardcoding the image inside the component is way less scalable than my JSON suggestion - perhaps there's a better solution that doesn't involve dynamic filenames being used in code.
Thanks for your help. I've looked at the possibilities and I have written a hoc which takes a function that adds specific props as a theme, this worked best for me.
Hi @bonjowi.
I am looking to do something similar to what you wanted to achieve. Could you paste a sample of how you were able to achieve this?
The HOC
import React from 'react';
import { ThemeProvider, ThemedStyleSheet } from '../styles/withStyles';
const withTheme = (themeName, propsMapper) => Component => {
class WithTheme extends React.Component {
constructor(props, context) {
super(props, context);
ThemedStyleSheet.registerTheme(themeName, propsMapper(props));
}
componentWillReceiveProps(nextProps) {
ThemedStyleSheet.registerTheme(themeName, propsMapper(nextProps));
}
render() {
return (
<ThemeProvider name={themeName}>
<Component {...this.props} />
</ThemeProvider>
);
}
}
return WithTheme;
};
export default withTheme;
The Component
import React from 'react';
import compose from 'recompose/compose';
import withTheme from '../withTheme';
const styles = ({ background, media }) => {
return {
root: {
backgroundImage: background,
},
};
});
function Component({ styles }) {
return <div {...css(styles.root)}/>;
}
export default compose(
withTheme('yourThemeName', ({ data }) => ({
background: data.background,
})),
withStyles(styles)
)(Component);