realvadim
realvadim

Reputation: 154

Can I pass name of object to use through props?

What I want to accomplish is this: I have created button component based on TouchableOpacity. In my app I have 3 types of differently looking buttons, they all share some styles and have something specific as well. Below is how my Button.js looks like:

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

class Button extends Component {
  render() {
    const { children, onPress, style } = this.props;
    const { buttonStyle, textStyle } = styles;

    return (
      <TouchableOpacity onPress={onPress} style={[buttonStyle]}>
        <Text style={[textStyle]}>
          {children}
        </Text>
      </TouchableOpacity>
    );
  }
}

//Commonly shared button styles
const styles = {
  textStyle: {
    alignSelf: 'center',
    fontSize: 17,
    paddingTop: 15,
    paddingBottom: 15
  },
  buttonStyle: {
    alignSelf: 'stretch',
    marginLeft: 15,
    marginRight: 15
  }
};

//Below are specific appearance styles
const black = {
  container: {
    backgroundColor: '#000'
  },
  text: {
    color: '#FFF'
  }
};

const white = {
  container: {
    backgroundColor: '#FFF'
  },
  text: {
    color: '#000'
  }
};

It would be great if I could use this button something like this:

<Button onPress={} style='black'>PLAY</Button>
<Button onPress={} style='white'>CANCEL</Button>

I.e. default buttonStyle and textStyle are applied from styles object. And I just want to pass a single word ('black', 'white') to reference additional style objects described in Button component.

I know I can create a helper method with switch, but I think there is a shorter way to do this. Is there?

Thanks a lot!

Upvotes: 3

Views: 471

Answers (3)

Henrik R
Henrik R

Reputation: 4972

I think this would be the shortest and cleanest way

import React, { PropTypes } from 'react';
import { Text, TouchableOpacity } from 'react-native';

const Button = ({ children, onPress, type }) => (
  <TouchableOpacity onPress={onPress} style={[styles.defaultButton, styles[type].button]}>
    <Text style={[styles.defaultText, styles[type].text]}>
      {children}
    </Text>
  </TouchableOpacity>
);

Button.propTypes = {
  children: PropTypes.node.isRequired,
  onPress: PropTypes.func.isRequired,
  type: PropTypes.oneOf(['white', 'black']).isRequired,
};

const styles = {
  defaultButton: {
    alignSelf: 'stretch',
    marginLeft: 15,
    marginRight: 15
  },
  defaultText: {
    alignSelf: 'center',
    fontSize: 17,
    paddingTop: 15,
    paddingBottom: 15
  },
  white: {
    button: {
      backgroundColor: '#FFF'
    },
    text: {
      color: '#000'
    }
  },
  black: {
    button: {
      backgroundColor: '#000'
    },
    text: {
      color: '#FFF'
    }
  },
};

export default Button;

Add type && style[type].button if type is not required prop. Like this:

const Button = ({ children, onPress, type }) => (
  <TouchableOpacity onPress={onPress} style={[styles.defaultButton, type && styles[type].button]}>
    <Text style={[styles.defaultText, type && styles[type].text]}>
      {children}
    </Text>
  </TouchableOpacity>
);

Button.propTypes = {
  children: PropTypes.node.isRequired,
  onPress: PropTypes.func.isRequired,
  type: PropTypes.oneOf(['white', 'black']),
};

Upvotes: 2

nanobar
nanobar

Reputation: 66345

You could do something like this:

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

// Commonly shared button styles
const defaultStyle = StyleSheet.create({
  textStyle: {
    alignSelf: 'center',
    fontSize: 17,
    paddingTop: 15,
    paddingBottom: 15,
  },
  buttonStyle: {
    alignSelf: 'stretch',
    marginLeft: 15,
    marginRight: 15,
  },
});

// Below are specific appearance styles
const black = StyleSheet.create({
  container: {
    backgroundColor: '#000',
  },
  text: {
    color: '#FFF',
  },
});

const white = StyleSheet.create({
  container: {
    backgroundColor: '#FFF',
  },
  text: {
    color: '#000',
  },
});

const themes = {
  black,
  white,
};

function Button({ children, onPress, theme }) {
  const buttonStyles = [defaultStyle.buttonStyle];
  const textStyles = [defaultStyle.textStyle];

  if (theme) {
    buttonStyles.push(themes[theme].container);
    textStyles.push(themes[theme].text);
  }

  return (
    <TouchableOpacity onPress={onPress} style={buttonStyles}>
      <Text style={textStyles}>
        {children}
      </Text>
    </TouchableOpacity>
  );
}

Button.propTypes = {
  onPress: PropTypes.func.isRequired,
  theme: PropTypes.string,
  children: PropTypes.oneOfType([
    PropTypes.arrayOf(PropTypes.node),
    PropTypes.node,
  ]),
};

export default Button;

Upvotes: 1

Codesingh
Codesingh

Reputation: 3384

As per my understanding towards your questions,please have a look at this:-

var styleChangeForButton,styleChangeForText
class Button extends Component {
  constructor(props)
  {
    super(props)
    const { children, onPress, style } = this.props;
    const { buttonStyle, textStyle } = styles;
    styleChangeForButton = [buttonStyle]
    styleChangeForText = [textStyle]

  }
  onPress()
  {
       styleChangeForButton = 'black'
       styleChangeForText = 'white'
  }

  render() {

  //

    style
    return (
      <TouchableOpacity onPress={onPress} style={styleChangeForButton}>
        <Text style={styleChangeForText}>
          {children}
        </Text>
      </TouchableOpacity>
    );
  }
}

//Commonly shared button styles
const styles = {
  textStyle: {
    alignSelf: 'center',
    fontSize: 17,
    paddingTop: 15,
    paddingBottom: 15
  },
  buttonStyle: {
    alignSelf: 'stretch',
    marginLeft: 15,
    marginRight: 15
  }
};

//Below are specific appearance styles
const black = {
  container: {
    backgroundColor: '#000'
  },
  text: {
    color: '#FFF'
  }
};

const white = {
  container: {
    backgroundColor: '#FFF'
  },
  text: {
    color: '#000'
  }
};

Upvotes: 1

Related Questions