Can I make dynamic styles in React Native?

CssReactjsReact Native

Css Problem Overview


Say I have a component with a render like this:

<View style={jewelStyle}></View>

Where jewelStyle =

  {
    borderRadius: 10,
    backgroundColor: '#FFEFCC',
    width: 20,
    height: 20,
  },

How could I make the background colour dynamic and randomly assigned? I've tried

  {
    borderRadius: 10,
    backgroundColor: getRandomColor(),
    width: 20,
    height: 20,
  },

But this makes all instances of View have the same colour, I want each one to be unique.

Any tips?

Css Solutions


Solution 1 - Css

I usually do something along the lines of:

<View style={this.jewelStyle()} />

...

jewelStyle = function(options) {
   return {
     borderRadius: 12,
     background: randomColor(),
   }
 }

Every time View is rendered, a new style object will be instantiated with a random color associated with it. Of course, this means that the colors will change every time the component is re-rendered, which is perhaps not what you want. Instead, you could do something like this:

var myColor = randomColor()
<View style={jewelStyle(myColor)} />

...

jewelStyle = function(myColor) {
   return {
     borderRadius: 10,
     background: myColor,
   }
 }

Solution 2 - Css

Yes you can and actually, you should use StyleSheet.create to create your styles.

import React, { Component } from 'react';
import {
    StyleSheet,
    Text,
    View
} from 'react-native';    

class Header extends Component {
    constructor(props){
        super(props);
    }    

    render() {
        const { title, style } = this.props;
        const { header, text } = defaultStyle;
        const combineStyles = StyleSheet.flatten([header, style]);    

        return (
            <View style={ combineStyles }>
                <Text style={ text }>
                    { title }
                </Text>
            </View>
        );
    }
}    

const defaultStyle = StyleSheet.create({
    header: {
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#fff',
        height: 60,
        paddingTop: 15,
        shadowColor: '#000',
        shadowOffset: { width: 0, height: 3 },
        shadowOpacity: 0.4,
        elevation: 2,
        position: 'relative'
    },
    text: {
        color: '#0d4220',
        fontSize: 16
    }
});    

export default Header;

And then:

<Header title="HOME" style={ {backgroundColor: '#10f1f0'} } />

Solution 3 - Css

If you still want to take advantage of StyleSheet.create and also have dynamic styles, try this out:

const Circle = ({initial}) => {


const initial = user.pending ? user.email[0] : user.firstName[0];

	const colorStyles = {
		backgroundColor: randomColor()
	};

	return (
		<View style={[styles.circle, colorStyles]}>
			<Text style={styles.text}>{initial.toUpperCase()}</Text>
		</View>
	);
};

const styles = StyleSheet.create({
	circle: {
		height: 40,
		width: 40,
		borderRadius: 30,
		overflow: 'hidden'
	},
	text: {
		fontSize: 12,
		lineHeight: 40,
		color: '#fff',
		textAlign: 'center'
	}
});

Notice how the style property of the View is set as an array that combines your stylesheet with your dynamic styles.

Solution 4 - Css

The easiest is mine:

<TextInput
  style={[
    styles.default,
    this.props.singleSourceOfTruth ?
    { backgroundColor: 'black' } 
    : { backgroundColor: 'white' }
]}/>

Solution 5 - Css

Had some issue syntactically. This worked for me

<Text style={[styles.textStyle,{color: 'red'}]}> Hello </Text>

const styles = StyleSheet.create({
   textStyle :{
      textAlign: 'center',   
      fontFamily: 'Arial',
      fontSize: 16
  }
  });

Solution 6 - Css

You'll want something like this:

var RandomBgApp = React.createClass({
    render: function() {

        var getRandomColor = function() {
            var letters = '0123456789ABCDEF'.split('');
            var color = '#';
            for (var i = 0; i < 6; i++ ) {
                color += letters[Math.floor(Math.random() * 16)];
            }
            return color;
        };

        var rows = [
            { name: 'row 1'},
            { name: 'row 2'},
            { name: 'row 3'}
        ];

        var rowNodes = rows.map(function(row) {
            return <Text style={{backgroundColor:getRandomColor()}}>{row.name}</Text>
        });

        return (
            <View>
                {rowNodes}
            </View>
        );

    }
});

In this example I take the rows array, containing the data for the rows in the component, and map it into an array of Text components. I use inline styles to call the getRandomColor function every time I create a new Text component.

The issue with your code is that you define the style once and therefore getRandomColor only gets called once - when you define the style.

Solution 7 - Css

I know this is extremely late, but for anyone still wondering here's an easy solution.

You could just make an array for the styles :

this.state ={
   color: "#fff"
}

style={[
  styles.jewelstyle, {
  backgroundColor: this.state.BGcolor
}

The second will override any original background color as stated in the stylesheet. Then have a function that changes the color:

generateNewColor(){
  var randomColor = '#'+Math.floor(Math.random()*16777215).toString(16);
  this.setState({BGcolor: randomColor})
}

This will generate a random hex color. Then just call that function whenever and bam, new background color.

Solution 8 - Css

Actually, you can write your StyleSheet.create object as a key with function value, it works properly but it has a type issue in TypeScript:

import React from 'react';
import { View, Text, StyleSheet } from 'react-native';

const SomeComponent = ({ bgColor }) => (
  <View style={styles.wrapper(bgColor)}>
    <Text style={styles.text}>3333</Text>
  </View>
);

const styles = StyleSheet.create({
  wrapper: color => ({
    flex: 1,
    backgroundColor: color,
  }),
  text: {
    color: 'red',
  },
});

Solution 9 - Css

Using object spread operator "..." worked for me:

<View style={{...jewelStyle, ...{'backgroundColor': getRandomColor()}}}></View>

Solution 10 - Css

  import React, { useContext, useMemo } from 'react';
  import { Text, StyleSheet, View } from 'react-native';
  import colors from '../utils/colors';
  import ThemeContext from './../contexts/ThemeContext';

  export default (props) => {
    const { theme } = useContext(ThemeContext);

    // Constructing styles for current theme
    const styles = useMemo(() => createStyles(theme), [theme]);

    return (
      <View style={styles.container}>
        <Text style={styles.label}>{label}</Text>
      </View>
    );
  };

  const createStyles = (theme: AppTheme) =>
    StyleSheet.create({
      container: { width: '100%', position: 'relative', backgroundColor: colors[theme].background },
      label: {
        fontSize: 13,
        fontWeight: 'bold',
      },
    });

colors.ts

export type AppTheme = 'dark' | 'light';

const light: Colors = {
  background: '#FFFFFF',
  onBackground: '#333333',
  gray: '#999999',
  grayLight: '#DDDDDD',
  red: 'red',
};

const dark: Colors = {
  background: '#333333',
  onBackground: '#EEEEEE',
  gray: '#999999',
  grayLight: '#DDDDDD',
  red: 'red',
};

const colors = {
  dark,
  light,
  primary: '#2E9767',
  secondary: '#F6D130',
};

export default colors;

Solution 11 - Css

Yes, you can make dynamic styles. You can pass values from Components.

First create StyleSheetFactory.js

import { StyleSheet } from "react-native";
export default class StyleSheetFactory {
  static getSheet(backColor) {
    return StyleSheet.create({
      jewelStyle: {
        borderRadius: 10,
        backgroundColor: backColor,
        width: 20,
        height: 20,
      }
    })
  }
}

then use it in your component following way

import React from "react";
import { View } from "react-native";
import StyleSheetFactory from './StyleSheetFactory'
class Main extends React.Component {
  getRandomColor = () => {
    var letters = "0123456789ABCDEF";
    var color = "#";
    for (var i = 0; i < 6; i++) {
      color += letters[Math.floor(Math.random() * 16)];
    }
    return color;
  };

  render() {
    return (
      <View>
        <View
          style={StyleSheetFactory.getSheet(this.getRandomColor()).jewelStyle}
        />
        <View
          style={StyleSheetFactory.getSheet(this.getRandomColor()).jewelStyle}
        />
        <View
          style={StyleSheetFactory.getSheet(this.getRandomColor()).jewelStyle}
        />
      </View>
    );
  }
}

Solution 12 - Css

<View 
 style={[styles.categoryItem,{marginTop: index <= numOfColumns-1 ? 10 : 0	}]}
>										

Solution 13 - Css

I know there are several answers, but i think the best and most simple is using a state "To change" is the state purpose.

export default class App extends Component {
	constructor(props) {
	  super(props);
      this.state = {
          style: {
              backgroundColor: "white"
          }
	  };
	}
	onPress = function() {
	  this.setState({style: {backgroundColor: "red"}});
	}
	render() {
	   return (
          ...
          <View style={this.state.style}></View>
          ...
       )
    }

}

Solution 14 - Css

You can bind state value directly to style object. Here is an example:

class Timer extends Component{
 constructor(props){
 super(props);
 this.state = {timer: 0, color: '#FF0000'};
 setInterval(() => {
   this.setState({timer: this.state.timer + 1, color: this.state.timer % 2 == 0 ? '#FF0000' : '#0000FF'});
 }, 1000);
}

render(){
 return (
   <View>

    <Text>Timer:</Text>
    <Text style={{backgroundColor: this.state.color}}>{this.state.timer}</Text>
  </View>
 );
 }
}

Solution 15 - Css

If you are using a screen with filters for example, and you want to set the background of the filter regarding if it was selected or not, you can do:

<TouchableOpacity style={this.props.venueFilters.includes('Bar')?styles.filterBtnActive:styles.filterBtn} onPress={()=>this.setFilter('Bar')}>
<Text numberOfLines={1}>
Bar
</Text>
</TouchableOpacity>

On which set filter is:

setVenueFilter(filter){
  var filters = this.props.venueFilters;
  filters.push(filter);
  console.log(filters.includes('Bar'), "Inclui Bar");
  this.setState(previousState => {
    return { updateFilter: !previousState.updateFilter };
  });
  this.props.setVenueFilter(filters);
}

PS: the function this.props.setVenueFilter(filters) is a redux action, and this.props.venueFilters is a redux state.

Solution 16 - Css

You can do something like this.

In your component:

const getRandomColor = () => {
  // you can use your component props here.
}

<View style={[styles.jewelStyle, {backgroundColor: getRandomColor()}]} />

Create your style using stylesheet:

const styles = StyleSheet.create({
  jewelStyle: {
    backgroundColor: 'red',
  },
});

Solution 17 - Css

If you are following the functional approach of React-Native, you can use a package called dynamic-styles that tries to solve exactly your problem.

// -- theme.js ------------------------------------------------------

// Initialization of a StyleSheet instance called 'styleSheet'
export const styleSheet = createStyleSheet({
    theme: /* optional theme */
});



// -- MyComponent.js -----------------------------------------------

// Create dynamic stylesheet that has access 
// to the previously specified theme and parameters
const useStyles = styleSheet.create(({theme, params}) => ({
    root: /* Dynamic Styles */,
    button: /* Dynamic Styles */,
    text: /* Dynamic Styles */,
}));

const MyComponent = (props) => {
    // Access dynamic styles using the created 'useStyles()' hook 
    // and specify the corresponding parameters
    const { styles } = useStyles({ color: props.color, fontSize: 10 });
    
    return (
      <div className={styles.root}>
          {/* */}
      </div>
    );
}

It basically allows you to create dynamic stylesheets and link them to functional Components using the React hook pattern.

-> Codesandbox

Solution 18 - Css

In case someone needs to apply conditions

 selectedMenuUI = function(value) {
       if(value==this.state.selectedMenu){
           return {
                flexDirection: 'row',
                alignItems: 'center',
                paddingHorizontal: 20,
                paddingVertical: 10,
                backgroundColor: 'rgba(255,255,255,0.3)', 
                borderRadius: 5
           }  
       } 
       return {
            flexDirection: 'row',
            alignItems: 'center',
            paddingHorizontal: 20,
            paddingVertical: 10
       }
    }

Solution 19 - Css

Here is what worked for me:

render() {
  const { styleValue } = this.props;
  const dynamicStyleUpdatedFromProps = {
    height: styleValue,
    width: styleValue,
    borderRadius: styleValue,
  }

  return (
    <View style={{ ...styles.staticStyleCreatedFromStyleSheet, ...dynamicStyleUpdatedFromProps }} />
  );
}

For some reason, this was the only way that mine would update properly.

Solution 20 - Css

you can use styled-components for react native it will provide you dynamic styling just like emotion or styled-components for web.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPete ThorneView Question on Stackoverflow
Solution 1 - CssJimmie BergView Answer on Stackoverflow
Solution 2 - CssdiegopratesView Answer on Stackoverflow
Solution 3 - CssCarlos AtencioView Answer on Stackoverflow
Solution 4 - CssVimNingView Answer on Stackoverflow
Solution 5 - CssYogesh LolusareView Answer on Stackoverflow
Solution 6 - CssColin RamsayView Answer on Stackoverflow
Solution 7 - Cssuser11007796View Answer on Stackoverflow
Solution 8 - Cssuser14415508View Answer on Stackoverflow
Solution 9 - CssCem RosoView Answer on Stackoverflow
Solution 10 - CssShankar SawantView Answer on Stackoverflow
Solution 11 - CssRajesh NasitView Answer on Stackoverflow
Solution 12 - CssKeshav GeraView Answer on Stackoverflow
Solution 13 - CssCesar AlonsoView Answer on Stackoverflow
Solution 14 - CssHossam GhareebView Answer on Stackoverflow
Solution 15 - CssFrikLimaView Answer on Stackoverflow
Solution 16 - Cssthe_haystackerView Answer on Stackoverflow
Solution 17 - CssBennoDevView Answer on Stackoverflow
Solution 18 - CssshankeyView Answer on Stackoverflow
Solution 19 - CssDaltronView Answer on Stackoverflow
Solution 20 - CssDevAddictView Answer on Stackoverflow