i want to create a function that returns the component with the props i want to assign with it? something like this, a reusable component for Text/View/Pressable with extracted styles as props, i personally find it's faster to style with styles as props in React Native:
const DynamicView = ({
children,
backfaceVisibility,
backgroundColor,
borderBottomColor,
borderBottomEndRadius,
borderBottomLeftRadius,
borderBottomRightRadius,
borderBottomStartRadius,
borderBottomWidth,
borderColor,
borderEndColor,
borderLeftColor,
borderLeftWidth,
borderRadius,
borderRightColor,
borderRightWidth,
borderStartColor,
borderStyle,
borderTopColor,
borderTopEndRadius,
borderTopLeftRadius,
borderTopRightRadius,
borderTopStartRadius,
borderTopWidth,
borderWidth,
opacity,
alignContent,
alignItems,
alignSelf,
aspectRatio,
borderEndWidth,
borderStartWidth,
bottom,
display,
end,
flex,
flexBasis,
flexDirection,
flexGrow,
flexShrink,
flexWrap,
height,
justifyContent,
left,
margin,
marginBottom,
marginEnd,
marginHorizontal,
marginLeft,
marginRight,
marginStart,
marginTop,
marginVertical,
maxHeight,
maxWidth,
minHeight,
minWidth,
overflow,
padding,
paddingBottom,
paddingEnd,
paddingHorizontal,
paddingLeft,
paddingRight,
paddingStart,
paddingTop,
paddingVertical,
position,
right,
start,
top,
width,
zIndex,
direction,
shadowColor,
shadowOffset,
shadowOpacity,
shadowRadius,
transform,
style,
...rest
}: ViewStyle & ViewProps) => (
<View
style={[
{
backfaceVisibility,
backgroundColor,
borderBottomColor,
borderBottomEndRadius,
borderBottomLeftRadius,
borderBottomRightRadius,
borderBottomStartRadius,
borderBottomWidth,
borderColor,
borderEndColor,
borderLeftColor,
borderLeftWidth,
borderRadius,
borderRightColor,
borderRightWidth,
borderStartColor,
borderStyle,
borderTopColor,
borderTopEndRadius,
borderTopLeftRadius,
borderTopRightRadius,
borderTopStartRadius,
borderTopWidth,
borderWidth,
opacity,
alignContent,
alignItems,
alignSelf,
aspectRatio,
borderEndWidth,
borderStartWidth,
bottom,
display,
end,
flex,
flexBasis,
flexDirection,
flexGrow,
flexShrink,
flexWrap,
height,
justifyContent,
left,
margin,
marginBottom,
marginEnd,
marginHorizontal,
marginLeft,
marginRight,
marginStart,
marginTop,
marginVertical,
maxHeight,
maxWidth,
minHeight,
minWidth,
overflow,
padding,
paddingBottom,
paddingEnd,
paddingHorizontal,
paddingLeft,
paddingRight,
paddingStart,
paddingTop,
paddingVertical,
position,
right,
start,
top,
width,
zIndex,
direction,
shadowColor,
shadowOffset,
shadowOpacity,
shadowRadius,
transform,
} as StyleProp<ViewStyle>,
style && style,
]}
{...rest}>
{children}
</View>
);
this is what i want to do, a reusable function that accepts a Component, e.g. Text, View, Pressable and assign the styles props:
import React from 'react';
import { Pressable, TextStyle, View, ViewProps, ViewStyle } from 'react-native';
type Comp = typeof View | typeof Pressable;
export const createDynamicElement = (RElement: Comp) => {
// How to dynamically pass TS props?
// e.g. for Pressable
class DynamicElement extends React.Component<
(ViewStyle | TextStyle) & typeof RElement
> {
render(): React.ReactNode {
// How to dynamically extract the styles key?
// const stylesKeys = keyExtractor(this.props)
const {
backfaceVisibility,
backgroundColor,
borderBottomColor,
borderBottomEndRadius,
borderBottomLeftRadius,
borderBottomRightRadius,
borderBottomStartRadius,
borderBottomWidth,
borderColor,
borderEndColor,
borderLeftColor,
borderLeftWidth,
borderRadius,
borderRightColor,
borderRightWidth,
borderStartColor,
borderStyle,
borderTopColor,
borderTopEndRadius,
borderTopLeftRadius,
borderTopRightRadius,
borderTopStartRadius,
borderTopWidth,
borderWidth,
opacity,
alignContent,
alignItems,
alignSelf,
aspectRatio,
borderEndWidth,
borderStartWidth,
bottom,
display,
end,
flex,
flexBasis,
flexDirection,
flexGrow,
flexShrink,
flexWrap,
height,
justifyContent,
left,
margin,
marginBottom,
marginEnd,
marginHorizontal,
marginLeft,
marginRight,
marginStart,
marginTop,
marginVertical,
maxHeight,
maxWidth,
minHeight,
minWidth,
overflow,
padding,
paddingBottom,
paddingEnd,
paddingHorizontal,
paddingLeft,
paddingRight,
paddingStart,
paddingTop,
paddingVertical,
position,
right,
start,
top,
width,
zIndex,
direction,
shadowColor,
shadowOffset,
shadowOpacity,
shadowRadius,
transform,
...rest
} = this.props;
return (
<RElement
{...rest}
style={[
{
backfaceVisibility,
backgroundColor,
borderBottomColor,
borderBottomEndRadius,
borderBottomLeftRadius,
borderBottomRightRadius,
borderBottomStartRadius,
borderBottomWidth,
borderColor,
borderEndColor,
borderLeftColor,
borderLeftWidth,
borderRadius,
borderRightColor,
borderRightWidth,
borderStartColor,
borderStyle,
borderTopColor,
borderTopEndRadius,
borderTopLeftRadius,
borderTopRightRadius,
borderTopStartRadius,
borderTopWidth,
borderWidth,
opacity,
alignContent,
alignItems,
alignSelf,
aspectRatio,
borderEndWidth,
borderStartWidth,
bottom,
display,
end,
flex,
flexBasis,
flexDirection,
flexGrow,
flexShrink,
flexWrap,
height,
justifyContent,
left,
margin,
marginBottom,
marginEnd,
marginHorizontal,
marginLeft,
marginRight,
marginStart,
marginTop,
marginVertical,
maxHeight,
maxWidth,
minHeight,
minWidth,
overflow,
padding,
paddingBottom,
paddingEnd,
paddingHorizontal,
paddingLeft,
paddingRight,
paddingStart,
paddingTop,
paddingVertical,
position,
right,
start,
top,
width,
zIndex,
direction,
shadowColor,
shadowOffset,
shadowOpacity,
shadowRadius,
transform,
},
]}
/>
);
}
}
return DynamicElement;
};
CodePudding user response:
I am not entirely sure if its a good approach or it would get messy over time.
Something like
getComponent(type:string, style:StyleProps, ...args) {
switch(type){
case'div':
return <div style={style} {...args} />
case'button':
return <button style={style} {...args}/>
case'span':
return <span style={style}{...args} />
default:
return null
}
}
CodePudding user response:
what i did is declare all ViewStyle keys in an array (extracted from react native typescript definitions):
export const viewStyleKeys = [
'backfaceVisibility',
'backgroundColor',
'borderBottomColor',
...
'shadowRadius',
'transform',
] as (keyof ViewStyle)[];
create a helper:
export const handleElementProps = <T>(
obj: T,
keys: (keyof ViewStyle | keyof TextStyle)[],
) => {
const stylesProps = Object.fromEntries(
keys.filter(key => key in obj).map(key => [key, obj[key as keyof T]]),
);
const elementProps = Object.fromEntries(
Object.keys(obj)
.filter(key => !keys.includes(key as keyof ViewStyle | keyof TextStyle))
.map(key => [key, obj[key as keyof T]]),
);
const elementStyles = createStyle(stylesProps);
return [elementStyles, elementProps];
};
const createStyle = (styles: ViewStyle | ImageStyle | TextStyle) =>
StyleSheet.create({
element: styles,
});
and use in a reusable view:
const DynamicView = ({ children, style, ...props }: ViewStyle & ViewProps) => {
const [elementStyles, elementNativeProps] = handleElementProps(
props,
viewStyleKeys,
);
return (
<View
{...elementNativeProps}
style={[style, elementStyles.element as ViewStyle]}>
{children}
</View>
);
};
it's just preference, think of it like classes but as props, i just don't like to declare styles everywhere