I have been using Styled-components with React web for a while now, but recently I have started working on a React Native app which I decided to use styled-compoents in. It's been great when styling components that have just the style property, such as the default react-native components.
The problem I've been having though is when I need to style a more complex component that has multiple style properties such as containerStyle, inputStyle, and others.
When it's only one style property with a different name I can do the following:
const StyledBadge = styled(({ style, ...rest }) => {
return <Badge {...rest} containerStyle={style} />;
})`
position: absolute;
right: 0;
top: 0;
`;
This works flawlessly but when the component has multiple styles, I have no idea what to do:
const StyledList = styled(({ style, ...rest }) => {
return <List {...rest} containerStyle={style} searchInputStyle={?} searchItemStyle={?} />;
})`
`;
With components like Gifted-React-Native-Chat is even worse because it has properties for passing properties as objects to its internal components, such as messageProps, listViewProps, containerProps and all of them have the style property.
Does anyone have any idea how to do that or if it's even possible?
I've been searching and trying to find a solution for this for a few days but I can't.
Thanks!
Here's how we ended up doing it.
Styled-components only work with the style prop but many custom components don't expose this prop. Instead they provide a *Style prop that gets passed to child component style props.
As an example, react-native-material-textfield has 5 style props.
We use the attrs function to keep the organization of styles in one file with the rest of the styled components.
This doesn't allow you to use traditional css syntax for the pseudo component, but it's the best we could think of to keep all styles organized.
Related
I want to style a component with my own custom className that has certain properties. Tailwind lets you do this through App.css, but in a react native application there is none. How do you add say a '.title' class to tailwind with certain properties?
.title {
font-size: 24px
font-weight: 800
}
Applying it to Text JSX object:
<Text className="title">Title Text!</Text>
I figured out this method of styling multiple of the same components. Nativewind and Tailwind suggest not using this method, but it works for both.
In your tailwind.config.js file, add the following line of code above your module.exports:
const plugin = require("tailwindcss/plugin");
module.exports = {...}
Then in your plugins list, add:
plugin(function ({ addComponents }) {
addComponents({
".title": {
fontWeight: 800,
fontSize: 24,
},
});
}),
Make sure your styling uses the same property names as react-native, and NOT css (fontWeight vs font-weight). Restart your server, and it should work!
You can use twrnc npm package for this. Install it from here.
Import it like this in the file at the top.
import tw from "twrnc";
And use it like this
<Text style={tw` text-2xl font-extrabold`}>Title Text!</Text>
I'm using the react-native-elements ui framework with ThemeProvider and trying to globally style the text of a component like this...
<ListItem bottomDivider>
<ListItem.Title>Name</ListItem.Title>
<ListItem.Input>DoB</ListItem.Input>
</ListItem>
I want to style this <ListItem.Input> text color red. So I've tried a ton of things similar to the code below, but I can't get anything working. Any ideas?
ListItem: {
inputStyle: {
color: "red"
}
}
I'd prefer to keep the styling global and not to do it inline, if possible.
You have to use ListItemInput
ListItemInput:{
style:{}
}
I'm currently trying to use Nav with react-router. The default behavior reloads the page, so I'm trying to use the Link component from react-router-dom.
It's quite difficult to preserve the default styling when overriding linkAs.
Is there any global way to override link navigation behavior?
Like defining a global link render function, which I can then set to render the Link component from react-router-dom?
Yes, it's possible!
2 things are required:
Make a wrapper component that translates the Nav API to react-router-dom links.
Specify the linkAs prop to the Nav component.
Wrapper component
This is a simple component that creates a react-router-dom link while using styles from Fabric:
import { Link } from "react-router-dom";
const LinkTo = props => {
return (
<Link to={props.href} className={props.className} style={props.style}>
{props.children}
</Link>
);
};
Specify component for use in Nav
<Nav groups={links} linkAs={LinkTo} />
Have also created a full working example at https://codesandbox.io/s/xenodochial-wozniak-y10tr?file=/src/index.tsx:605-644
I'm starting to learn React Native, and I'm trying to create grid of 3 columns with images. I've been using the numColumns prop of the FlatList to specify 3 columns, and then setting flex:1 for my images so they should fill the space of the column. However flex:1 makes none of my images appear, while trying height:100,aspectRatio:1 shows all of my images in columns. Any idea why this is? My code is down below:
export default class ArtScrollView extends React.Component {
_renderItem = (item) =>
(
<Image style={styles.art} source={{uri:item.item.imgFilePath}}/>
)
render() {
return(
<FlatList numColumns={3}
data={Object.values(this.props.pods)}
renderItem={this._renderItem}/>
);
}
}
const styles = StyleSheet.create({
art:{
height:100,
aspectRatio:1,
//flex:1, <- Having this instead of specifying the height doesn't work
marginRight:10,
}
});
Auto-sizing images in ReactNative does not work. It just doesn't. You need to know the dimensions of images before you show them.
It is quite easy to use var {height, width} = Dimensions.get('window'); and use those as your reference for your images' sizing.
Use the inspector and see (and understand) what FlatList actually renders for you. You may understand why things do not work (not just in this case but generally)
I am using TextInput in multiple scenes to render "form" elements. They all share the same style, so what is good practice in React Native in terms of styling? I mean, I could define a style for the TextInput in every single component scene, but is there a way to be more DRY?
Wrap your TextInput in your own component. Add styles to it, and define props that you use a lot with that component. You can also pass other props (not explicitly defined) for example by using const { label, value, placeholder, onChange, multiline, onSubmit, ...passProps } = this.props; and then <TextInput label={label} ... {...passProps} />.