How to style React class component? - javascript

I defined class component for my form in React but I am getting an error when I want to style it.
In functional component I use const useStyles = theme => ({}) and const classes = useStyles(); to style functional component and it works.
Now I need to style class component and I defined constants where I put all my style code for the class component.
In class component element (ex. Box) I use style property like :
<Box style={nameOfTheContant}/>
and it works.
In my class component I need to implement media queries and I use Material UI breakpoints for that but when I add :
const classes = useStyles();
inside class component, it does not work.
My goal is to use media queries inside class component because I need to have special CSS style for mobile device. In functional component I use theme.breakpoints.down["sm"] but in class component it is not possible.
Here is the simplified code:
const useStyles = theme => ({
searchPanel: {
display: "flex",
justifyContent: "center",
backgroundColor:"red",
[theme.breakpoints.down("sm")]: {
backgroundColor:"green"
}}});
export default class SearchPanel extends Component {
render() {
const classes = useStyles();
return (
<h1 className={classes.searchPanel}>Text</h1>
)}}

you can use withStyles when styling class components:
// your typical imports here ...
import { withStyles } from "#material-ui/styles";
const styles = theme => ({
searchPanel: {
display: "flex",
justifyContent: "center",
backgroundColor:"red",
[theme.breakpoints.down("sm")]: {
backgroundColor:"green"
}
}
});
class SearchPanel extends Component {
render() {
const classes = useStyles();
return (<h1 className={classes.searchPanel}>Text</h1>));
}
}
export default withStyles(styles)(SearchPanel);

Related

what is the best way to setParams to navigation before setting the options for Navigation using setOptions?

I wanna know the best way to set the params and options for react native navigation in a class component.
note that the same params are used in options.
when I put all code in the constructor I got params undefined because of timing issue.
and it works. for me in one case when I added option in componentDidMount , I will write some examples in the code below.
1- first case using class component (it's working)
type Props = {
navigation: NavigationProp<any>;
route: RouteProps<{ Example: {title: string} }, 'Example'>
}
export default class Example extends Component <Props> {
constructor(props: Props){
super(props)
this.props.navigation.setParams({ title: 'title' });
}
componentDidMount(){
this.props.navigation.setOptions({ title: this.props.route.params.title })
}
...
}
2 - second case using FC: (not using this example but I think it's also the best way todo for the FC).
export function Example: React.FC = () => {
const navigation = useNavigation();
const route = useRoute();
useLayoutEffect(()=>{
navigation.setParams({ title: 'title' });
navigation.setOptions({ title: route.params.title })
})
...
}
so I hope my question is clear, is that theright way to set Header options with the lates Navigation on React Native?
constructor is the first step in component lifecycle, and you are setting params inside that, which means there is a prop that is going to be updated.
so we need a function that understands every update on a state or received props, and that listener is nothing except "componentDidUpdate(){}" 🤟:
import {NavigationProp, RouteProp} from '#react-navigation/native';
import React, {Component} from 'react';
import {Text, StyleSheet, View} from 'react-native';
type Props = {
navigation: NavigationProp<any>;
route: RouteProp<{Example: {title: string}}, 'Example'>;
};
export default class Example extends Component<Props> {
constructor(props: Props) {
super(props);
this.props.navigation.setParams({title: 'title'});
}
componentDidUpdate() {
this.props.navigation.setOptions({title: this.props.route.params.title});
}
render() {
return (
<View style={styles.container}>
<Text style={styles.textStyle}>Use component did update :)</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
padding: 30,
},
textStyle: {
color: 'black',
fontSize: 20,
fontWeight: 'bold',
},
});

How to override style of nested Material UI component from the ancestors?

I am using a component from an external library that does not allow me to change much of its style, but I would like to change the style of a button that is a material ui button, when inspecting the element it clearly shows the classes MuiButtonBase-root MuiIconButton-root MuiIconButton-colorInherit
how can I override the MuiIconButton-root style, for instance? this is my component:
class MyComponent extends Component {
render() {
const { classes } = this.props;
return (
<div className={classes.myComponent}>
<3rdPartyComponent />
</div>
);
}
}
export default withStyles(styles)(MyComponent)
I have tried declaring my styles function as follows, without success:
const styles = theme => ({
myComponent: {
"&.MuiIconButton-root": {
padding: "0px"
}
}
});
Can anybody help me? Thanks in advance.
Let's say that the class name generated for myComponent is myComponent-jss123. The selector you used in your styles (&.MuiIconButton-root) would be equivalent to .myComponent-jss123.MuiIconButton-root which would match any element that has both of these classes applied to it. I believe your intent was to match icon buttons which are descendants of the div on which you are applying the myComponent class. In this case you need to use the descendant combinator represented by a space, so the appropriate styles would look like the following:
const styles = theme => ({
myComponent: {
"& .MuiIconButton-root": {
padding: 0
}
}
});
Here's a full working example:
import React from "react";
import IconButton from "#material-ui/core/IconButton";
import DeleteIcon from "#material-ui/icons/Delete";
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles({
myComponent: {
"& .MuiIconButton-root": {
padding: 0
}
}
});
const ThirdPartyComponent = () => {
return (
<div>
I'm a third party component that contains an IconButton:
<IconButton color="primary">
<DeleteIcon />
</IconButton>
</div>
);
};
export default function App() {
const classes = useStyles();
return (
<div className={classes.myComponent}>
<ThirdPartyComponent />
</div>
);
}
Related documentation:
https://cssinjs.org/jss-plugin-nested/?v=v10.0.4#use--to-reference-selector-of-the-parent-rule
https://developer.mozilla.org/en-US/docs/Web/CSS/Class_selectors
https://developer.mozilla.org/en-US/docs/Web/CSS/Descendant_combinator

Material UI withStyles on multiple styled HoCs

My application uses HoCs for its modals and I use withStyles to style them, when I apply multiple HoCs to one component however the classes prop of the first HoC is passed to the next in the compose of the component.
Example HoC1:
const styles = themes => ({
HoCOneStyle: {
margin: 'auto'
}
})
const withHoCOne = (WrappedComponent) => {
class HoCOne extends React.Component {
<HoC Stuff className={classes.HoCOneStyle} />
<WrappedComponent
{...this.props}
/>
}
return withStyles(styles, {withTheme: true})(HoCOne);
}
export default withHoCOne;
Example HoC2:
const styles = themes => ({
HoCTwoStyle: {
margin: 'auto'
}
})
const withHoCTwo = (WrappedComponent) => {
class HoCTwo extends React.Component {
<HoC Stuff className={classes.HoCTwoStyle} />
<WrappedComponent
{...this.props}
/>
}
return withStyles(styles, {withTheme: true})(HoCTwo);
}
export default withHoCTwo;
Example component:
class DemoComponent extends React.Component {
render() {
return (
<Component Stuff />
)
}
}
export default compose(
withHoCOne,
withHoCTwo
)(DemoComponent)
If run this code would throw an error in the console saying:
Warning: Material-UI: the key 'HoCOneStyle' provided to the classes
property is not implemented in HoCTwo. You can only override one of
the following: HoCTwoStyle.
How do I avoid throwing this error? It doesn't actually stop anything from working I just don't want errors in my console.
You just need to avoid passing the classes property from HoCOne into HoCTwo. When you include the classes property on something that is also using withStyles it triggers Material-UI's mergeClasses functionality.
You should be able to solve this with something like the following:
render() {
const {classes, ...otherProps} = this.props;
return <><HoC className={classes.HoCOneStyle} /><WrappedComponent
{...otherProps}
/></>;
}

How to create a custom Text - react native

I completed my project now I want to set my custom font to all Text component.
I think the best way is to create a custom Text component and replace it with default Text of react-native.
now how can I creating a custom Text component with default style?
To achieve that, you need to have a react native component that is configurable via style or other properties once instantiated.
For example you can have your custom react native component CustomText like this:
1. Function component
If you prefer the new way and you'll use it with hooks, use this part:
// CustomText.js
import React from 'react';
import {
Text,
StyleSheet,
} from 'react-native';
export default function CustomText(props) {
return (
<Text style={[styles.defaultStyle, props.style]}>
{props.children}
</Text>
);
}
const styles = StyleSheet.create({
// ... add your default style here
defaultStyle: {
},
});
2. Class component
If you prefer the old way with classes use this part:
// CustomText.js
import React from 'react';
import {
Text,
StyleSheet,
} from 'react-native';
export default class CustomText extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<Text style={[styles.defaultStyle, this.props.style]}>
{this.props.children}
</Text>
);
}
}
const styles = StyleSheet.create({
// ... add your default style here
defaultStyle: {
},
});
And then on your main component you import and call that custom component, something like this:
import CustomText from './CustomText';
//... other imports go here.
// in the render method you call your CustomText component.
render(){
//...
<CustomText style={{ fontWeight: 60, }}>
This is custom Text
</CustomText>
}
Note: If you want only to change the style I think #Yanush solution is the best for that case.
I hope this is helpful.
I would suggest using a style instead of a custom component but it's up to you.
In my project I have created a file named "commonStyles.js" that looks like this:
export default StyleSheet.create({
textTitle: {
fontSize: 20,
color: '#dddddd',
fontFamily: 'YourCustomFont',
},
});
then I'm importing this file wherever needed using:
import stylesCommon from './styles/stylesCommon';
and each text that needs to be changed should look like this:
<Text style={stylesCommon.textTitle}>
This is my title
</Text>
this guide will help you on how to apply custom fonts, I have been using the method in my apps.
To create a custom text component
export default Text = (props)=>{
return(
<Text style={[styles.defaultStyles,props.style]}>{props.children}</Text>
)
}
Now in all the files where you have used Text from react native remove import from react native and add
import Text from './path/to/component'

Javascript react-jss hover not changing color

I am trying out React-Jss from cssinjs.org/react.jss and this is what I've done upto now:
Installation:
npm install --save react-jss
I then tested this file where I added a Hover to the footer just to give this a test:
import React from 'react';
import injectSheet from 'react-jss';
const style = {
Footer: {
backgroundColor: '#000000',
},
'&:hover': {
backgroundColor: '#ff0000',
}
};
export class Footer extends React.Component {
render() {
return (
<Footer>This is the footer</Footer>
);
}
}
export default injectSheet(style);
When I hover over the Footer component I would expect the footer to turn red but nothing is happening.
I'm I missing something or is something wrong in the syntax?
There's a handful of reasons the code above isn't working. There's issues with your React code beyond the JSS syntax.
In regards to the JSS style declaration specifically, let's first make sure you understand what you're declaring in the style object. The properties of the style object (in your case Footer, are the class names that you want to define and as such should probably be all lowercase. The value of each of those properties is an object containing the CSS styles that you want applied by that class. If you want to define a hover styles for a given class then you would declare those styles inside of the class's style object like so:
const style = {
footer: {
backgroundColor: '#000000',
'&:hover': {
backgroundColor: '#ff0000',
}
}
};
I suspect you're attempting to follow the first code example under 'Usage' in the package's readme. Here's a working example that follows that approach.
import React from 'react'
import injectSheet from 'react-jss'
const style = {
footer: {
backgroundColor: '#000000',
'&:hover': {
backgroundColor: '#ff0000'
}
}
}
const Footer = ({sheet}) => (
<div className={sheet.classes.footer}>This is the footer</div>
)
export default injectSheet(style)(Footer)
Below is a working example that utilizes the advantages of ES6 in case you're interested.
import React, {PropTypes} from 'react';
import injectSheet from 'react-jss';
const style = {
footer: {
backgroundColor: '#000000',
'&:hover': {
backgroundColor: '#ff0000'
}
}
};
#injectSheet(style)
export default class Footer extends React.Component {
static propTypes = {
sheet: PropTypes.object.isRequired
}
render() {
const {sheet} = this.props
return (
<div className={sheet.classes.footer}>This is the footer</div>
);
}
}

Categories

Resources