How to import and export styles in react native? - css

I am new to react native.I learned the benefits of components, embedding external styles.Now I am trying to use global styles.I'd like to use the same styles of text, button throughout my app.
Better not to repeat the styles in every component, I'd like to create separate text.js, button.js under styles package to customizing view styles.
Here is my project structure.I want to import text.js into my index.js.
index.js
import { AppRegistry } from 'react-native';
import React, {Component} from 'react';
import {
Text
} from 'react-native';
import text from './App/styles';
export default class FirstApp extends Component{
render(){
return (
<Text styles={text.p}>Customising React</Text>
);
}
}
AppRegistry.registerComponent('FirstApp', () => FirstApp);
text.js
import{
StyleSheet
} from 'react-native';
export default const text = StyleSheet.create({
p: {
color: 'blue',
fontSize: 14
}
});
Is there any way to import my text.js style into text view in index.js?

Export default const is invalid.
If you want text to be a default export you will need to define it and export in separate statements.
const text = StyleSheet.create({...});
export default test;
Also it looks like your import path does not match your actual application structure.
import text from './App/styles';
change to
import text from './styles/text.js';

create a new file call 'style.js'
export const customStyle = StyleSheet.create({
blueblue:{
color: blue
}
})
and in your component file
import {customStyle} from './style'
...
<Text style={customStyle.blueblue}>Hi</Text>

create this on style.js
const style = StyleSheet.create({
p: {
color: 'blue',
fontSize: 14
}
})
export default style;
and import anywhere you want
like this
import Style from './(path to file)/style'
use style like this
<View style={[Style.p, {
padding: 20,
backgroundColor: 'grey',
justifyContent: 'center',
alignContent: 'center'
}]}>
if single use
<View style={Style.p}>
so this may help

Related

How can I override styling for ListItemButton when it's selected?

I'm trying to override the existing styling for a button in MUI. This is my first time using MUI, and I installed my project with the default emotion as a styling engine. I tried to use the css() method as specified here : The css prop however it doesn't seem to be working, even on the example case provided.
I would have tried to add a custom css file to handle :select, but I'm using state in my component to change from selected to not selected.
import * as React from "react";
import Avatar from "#mui/material/Avatar";
import ListItemText from "#mui/material/ListItemText";
import ListItemButton from "#mui/material/ListItemButton";
import { useState } from "react";
import { css } from "#emotion/react";
const ProfileInfo = ({ userCredentials, userPicture }) => {
const [selected, setSelected] = useState(false);
return (
<ListItemButton
selected={selected}
onClick={() => setSelected((prev) => !prev)}
css={css`
::selection {
color: #2e8b57;
}
:focus {
color:#2e8b57;
}
:active {
color:#2e8b57
}
`}
>
<Avatar
alt={userCredentials}
src={userPicture}
sx={{ width: 24, height: 24 }}
/>
<ListItemText primary={userCredentials} sx={{ marginLeft: 3 }} />
</ListItemButton>
);
};
export default ProfileInfo;
Working examples on Code Sandbox
I have made a similar example using Code Sandbox, which you can find here https://codesandbox.io/s/amazing-gagarin-gvl66n. I show a working implementation using:
The css prop
The sx prop
Using the css prop
There's two things you need to do to make your code work using Emotion's css prop.
Add the following lines, which is also in the example, at the top of the file where you are using the css prop. This will tell your app how to handle the css prop.
/* eslint-disable react/react-in-jsx-scope -- Unaware of jsxImportSource */
/** #jsxImportSource #emotion/react */
Target the classes Material UI provides for the List Item Button component. For example, if I want to style the List Item Button when selected is true, I would target the .Mui-selected class.
I am assuming you wanted to style the background color of the List Item Button rather than the color. Styling the color changes the font color. However, if you wanted to change the font color, you can just change each instance of background-color to color.
Putting it altogether:
/* eslint-disable react/react-in-jsx-scope -- Unaware of jsxImportSource */
/** #jsxImportSource #emotion/react */
import * as React from "react";
import Avatar from "#mui/material/Avatar";
import ListItemText from "#mui/material/ListItemText";
import ListItemButton from "#mui/material/ListItemButton";
import { useState } from "react";
import { css } from "#emotion/react";
const ProfileInfo = ({ userCredentials, userPicture }) => {
const [selected, setSelected] = useState(false);
return (
<ListItemButton
selected={selected}
onClick={() => setSelected((prev) => !prev)}
css={css`
&.Mui-selected {
background-color: #2e8b57;
}
&.Mui-focusVisible {
background-color: #2e8b57;
}
:hover {
background-color: #2e8b57;
}
`}
>
<Avatar
alt={userCredentials}
src={userPicture}
sx={{ width: 24, height: 24 }}
/>
<ListItemText primary={userCredentials} sx={{ marginLeft: 3 }} />
</ListItemButton>
);
};
export default ProfileInfo;
Alternative: Using the SX prop
The sx prop can be used to override styles with all Material UI components. You are already using this for the Avatar and ListItemText components in your example.
Using the sx prop, the equivalent code would be:
import * as React from "react";
import Avatar from "#mui/material/Avatar";
import ListItemText from "#mui/material/ListItemText";
import ListItemButton from "#mui/material/ListItemButton";
import { useState } from "react";
const ProfileInfo = ({ userCredentials, userPicture }) => {
const [selected, setSelected] = useState(false);
return (
<ListItemButton
selected={selected}
onClick={() => setSelected((prev) => !prev)}
sx={{
"&.Mui-selected": {
backgroundColor: "#2e8b57"
},
"&.Mui-focusVisible": {
backgroundColor: "#2e8b57"
},
":hover": {
backgroundColor: "#2e8b57"
}
}}
>
<Avatar
alt={userCredentials}
src={userPicture}
sx={{ width: 24, height: 24 }}
/>
<ListItemText primary={userCredentials} sx={{ marginLeft: 3 }} />
</ListItemButton>
);
};
export default ProfileInfo;
It looks like MUI components doesn't use standard CSS rules but instead has a defined set of CSS rules you can modify https://mui.com/material-ui/api/list-item/#props.

How to Override the style of Layout component in React?

I am using Next.js with Material-UI as the framework.
I have Layout component that wraps the contents with Material-UI <Container>.
I would like to override the style of Layout that limits the width of background, so that the background would extend to the full screen.
components/Layout.js
import { Container } from '#material-ui/core';
export default function Layout({ children }) {
return <Container>{children}</Container>;
}
pages/_app.js
import Layout from '../components/Layout';
...
<Layout>
<Component {...pageProps} />
</Layout>
...
pages/index.js
export default function App() {
return (
<div style={{ backgroundColor: "yellow" }}>
Home Page
</div>
)
}
Using Layout component comes in handy in most cases but sometimes I do want to override the certain styles of Layout from the child component.
In this case, how do I override the style of Layout component that puts the limit on maxWidth?
I tried to add {width: '100vw'} inside the style of pages/index.js, but did not work.
Any help would be appreciated.
Link to the SandBox
Using React Context is how I've solved this issue.
context/ContainerContext.js
import React from 'react';
const ContainerContext = React.createContext();
export default ContainerContext;
components/Layout.js
import React, { useState } from 'react';
import { Container } from '#material-ui/core';
import ContainerContext from '../context/ContainerContext';
export default function Layout({ children }) {
const [hasContainer, setHasContainer] = useState(true);
const Wrapper = hasContainer ? Container : React.Fragment;
return (
<ContainerContext.Provider value={{ hasContainer, setHasContainer }}>
<Wrapper>{children}</Wrapper>
</ContainerContext.Provider>
);
}
pages/index.js
import { useContext, useLayoutEffect } from 'react';
import ContainerContext from '../context/ContainerContext';
export default function App() {
const { setHasContainer } = useContext(ContainerContext);
// Where the magic happens!
useLayoutEffect(() => {
setHasContainer(false);
}, []);
return (
<div style={{ backgroundColor: "yellow" }}>
Home Page
</div>
);
}

Material-ui style type override

I'd like to modify MuiIconButton-root class when I use MuiSvgIcon with fontSizeSmall.
import React from 'react'
import { createMuiTheme, ThemeProvider } from '#material-ui/core/styles';
const theme = createMuiTheme({
overrides: {
MuiSvgIcon: {
fontSizeSmall: {
padding: "5px"
}
}
}
});
export default function Root(props) {
return (
<ThemeProvider theme={theme}>
<MyApp />
</ThemeProvider>
)
}
I've modified MuiSvgIcon, but it can't modify MuiButtonBase-root.
Is there any way to override the padding value of MuiIconButton-root when I use small MuiSvgIcon?
Following the picture:
yes you can override the style of root like this, I am not creating your exact scenario but I am going to show you the same functionality with a button from Material UI, first get all the files needed:
npm install #material-ui/styles
npm install #material-ui/core
and then:
//other react imports
import { makeStyles, withStyles } from '#material-ui/core/styles'; //you need to include this to change the style
import Button from '#material-ui/core/Button'; //this is just the button
const useStyles = theme => ({
root: {
'& > *': {
margin: theme.spacing(1),
},
},
button: {
fontSize: "16px",
fontWeight: "600",
textAlign: "center",
border: "none",
cursor: "pointer",
color: "#fff",
backgroundColor: "#C8385E"
}
});
class Welcome extends React.Component {
render() {
return (<div>
<Button
className={classes.button}
variant="contained" component="span">
BUTTON TEXT
</Button>
</div>);
}
}
export default withStyles(useStyles)(Welcome);
you need to export the class like shown above, include the "withStyles" and pass in the styles that you have, here its called "useStyles" and then pass the class name. this way you can edit the styles in the UseStyles and it will actually show those changes on the screen.

How to allow customization of a React component's style via props, when withStyles api is used?

I'm writing some simple reusable component for our React(with MaterialUI) application.
The problem is, that i want to allow different styles of this same reusable component, to be customized via props, by the consuming component.
This is some of the code:
import { withStyles } from '#material-ui/core';
const styles = theme => ({
image: {
maxHeight: '200px'
}
});
render() {
const classes = this.props.classes
return (
<div>
...
<img className={classes.image} src={this.state.filePreviewSrc} alt="" />
...
</div>
);
}
Let's say, i want to allow the programmer to customize the appearance of classes.image. Can the hard-coded image class be overwritten somehow?
Is using withStyles api is even the correct approach, for creating components whose appearance can be customized by the consuming component/programmer?
There are three main approaches available for how to support customization of styles:
Leverage props within your styles
Leverage props to determine whether or not certain classes should be applied
Do customization via withStyles
For option 3, the styles of the wrapping component will be merged with the original, but the CSS classes of the wrapping component will occur later in the <head> and will win over the original.
Below is an example showing all three approaches:
ReusableComponent.js
import React from "react";
import { withStyles } from "#material-ui/core/styles";
const styles = {
root: props => ({
backgroundColor: props.rootBackgroundColor
? props.rootBackgroundColor
: "green"
}),
inner: props => ({
backgroundColor: props.innerBackgroundColor
? props.innerBackgroundColor
: "red"
})
};
const ReusableComponent = ({ classes, children, suppressInnerDiv = false }) => {
return (
<div className={classes.root}>
Outer div
{suppressInnerDiv && <div>{children}</div>}
{!suppressInnerDiv && (
<div className={classes.inner}>
Inner div
<div>{children}</div>
</div>
)}
</div>
);
};
export default withStyles(styles)(ReusableComponent);
index.js
import React from "react";
import ReactDOM from "react-dom";
import { withStyles } from "#material-ui/core/styles";
import ReusableComponent from "./ReusableComponent";
const styles1 = theme => ({
root: {
backgroundColor: "lightblue",
margin: theme.spacing(2)
},
inner: {
minHeight: 100,
backgroundColor: "yellow"
}
});
const Customization1 = withStyles(styles1)(ReusableComponent);
const styles2 = {
inner: {
backgroundColor: "purple",
color: "white"
}
};
const Customization2 = withStyles(styles2)(ReusableComponent);
function App() {
return (
<div className="App">
<ReusableComponent>Not customized</ReusableComponent>
<Customization1>Customization 1 via withStyles</Customization1>
<Customization2>Customization 2 via withStyles</Customization2>
<ReusableComponent rootBackgroundColor="lightgrey" suppressInnerDiv>
Customization via props
</ReusableComponent>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

How to reuse react-native StyleSheet (styles) in react?

// react-native example
import { StyleSheet, View } from 'react-native';
const styles = {
container: {
borderRadius: 4,
borderWidth: 0.5,
borderColor: '#d6d7da',
}
}
const stylesRN = StyleSheet.create(styles);
<View style={stylesRN.container}></View>
What the best way to reuse
// inner styles
{
borderRadius: 4,
borderWidth: 0.5,
borderColor: '#d6d7da',
}
in both react-native and react?
What i want to achieve in pseudocode (or another way of reuse in React):
<div style={magicAdapter(styles.container)}>Hello World!</div>
Problem: It is impossible to reuse all react-native inline-styles in react as is without magicAdapter.
What you could do is store all your styles in an object in some file e.g. const containerStyles = { borderRadius: 2 }, export it, then for React Native use the StyleSheets javascript class to create the styles for your div container
import {containerStyles} from '../someFile.js'
const styles = StyleSheets.create({
container: containerStyles
})
then for React you could do inline styling with the same object, but be aware that not all styles supported in StyleSheets can be used for inline styling, so if you want to do something equivalent there's libraries out there like emotion.js to dynamically load CSS in JS
https://github.com/emotion-js/emotion
Heres an example
import {css} from 'emotion'
import {containerStyle} from '../someFile'
const getContainerStyles = css`
border-radius: ${containerStyle.borderRadius}
`
export default class SomeClass extends Component {
render() {
return(
<div
style={getContainerStyles}
>
</div>
)
}
}
I hope this helps
You could concatenate the style of your new component with the style of container, like below
const styles = StyleSheet.create({
container: {
borderRadius: 4,
borderWidth: 0.5,
borderColor: '#d6d7da',
},
newComponent:{
// New component style
}
});
<View style={[styles.container, styles.newComponent]}>
</View>
// your component file name (button.js)
import React, { Component } from 'react';
// import the style from another file present in the same directory
import styles from 'button.style.js';
// you can reuse this style in another component also
class Button extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.buttonText}> Press Me! </Text>
</View>
);
}
}
export default Button;
// your style file name ( "button.style.js")
import { StyleSheet } from 'react-native';
export default StyleSheet.create({
container: {
padding: 10,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#43a1c9',
},
buttonText: {
fontSize: 20,
textAlign: 'center'
}
});

Resources