Search code examples
react-nativebuttontouchableopacity

React Native - The Color of TouchableOpacity Button Should Change Without Map


I have only two buttons, and I want their backgroundColor to be changed when pressing. I don't want to use map as there are only two buttons. I have tried some ways to approach what I expect, but I am at a loss what to do.

RoundedButtonSet :


const styles = StyleSheet.create({
  container: {
    marginBottom: 20,
  },
});

const RoundedButtonSet = ({ firstBtn, secondBtn, contentStyle }) => {
  return (
    <View style={[styles.container, contentStyle]}>
      <RoundedButtons firstBtn={firstBtn} secondBtn={secondBtn} />
    </View>
  );
};

RoundedButtons :

const styles = StyleSheet.create({
  container: {
    flexDirection: 'row',
    marginHorizontal: 15,
    height: 40,
    alignItems: 'center',
  },
  btn: {
    flex: 1,
    borderWidth: 1,
    borderColor: colors.very_light_pink,
    borderRadius: 6,
    paddingVertical: 13,
    height: 40,
  },
  btnTextStyle: {
    fontSize: 12,
    fontWeight: 'normal',
    color: colors.very_light_pink_five,
    textAlign: 'center',
  },
  left: {
    borderTopRightRadius: 0,
    borderBottomRightRadius: 0,
    borderColor: colors.very_light_pink,
  },
  right: {
    borderTopLeftRadius: 0,
    borderBottomLeftRadius: 0,
    borderLeftWidth: 0,
  },
  backgroundColor: {
    backgroundColor: colors.iris,
  },
  textColor: {
    color: colors.white_two,
  },
});

const RoundedButtons = ({ firstBtn, secondBtn, contentStyle, onPress }) => {
  const [isClicked, setIsClicked] = useState(true);

  return (
    <View style={[styles.container, contentStyle]}>
      <TouchableOpacity
        style={[styles.btn, styles.left, isClicked && styles.backgroundColor]}
        onPress={() => setIsClicked(!isClicked)}
      >
        <Text style={[styles.btnTextStyle, isClicked && styles.textColor]}>
          {firstBtn}
        </Text>
      </TouchableOpacity>
      <TouchableOpacity
        style={[styles.btn, styles.right]}
        onPress={() => setIsClicked()}
      >
        <Text style={[styles.btnTextStyle]}>{secondBtn}</Text>
      </TouchableOpacity>
    </View>
  );
};

RoundedButtons.propTypes = {
  firstBtn: Text.propTypes,
  secondBtn: Text.propTypes,
};

export default RoundedButtons;

Should I give index directly to each button? I have got this idea, but the problem is I have no idea how to access..


Solution

  • You can have a simple state to keep track of which button is pressed and use that to apply styles conditionally.

    Here is the working example: Expo Snack

    enter image description here

    import React, { useState } from 'react';
    import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
    import Constants from 'expo-constants';
    
    // You can import from local files
    import AssetExample from './components/AssetExample';
    
    // or any pure javascript modules available in npm
    import { Card } from 'react-native-paper';
    
    const styles = StyleSheet.create({
      container: {
        flexDirection: 'row',
        marginHorizontal: 15,
        height: 40,
        alignItems: 'center',
      },
      btn: {
        flex: 1,
        borderWidth: 1,
        borderColor: 'pink',
        borderRadius: 6,
        paddingVertical: 13,
        height: 40,
      },
      btnTextStyle: {
        fontSize: 12,
        fontWeight: 'normal',
        color: 'pink',
        textAlign: 'center',
      },
      left: {
        borderTopRightRadius: 0,
        borderBottomRightRadius: 0,
        borderColor: 'pink',
      },
      right: {
        borderTopLeftRadius: 0,
        borderBottomLeftRadius: 0,
        borderLeftWidth: 0,
      },
      backgroundColor: {
        backgroundColor: 'black',
      },
      textColor: {
        color: 'white',
      },
    });
    
    const RoundedButtons = ({ firstBtn, secondBtn, contentStyle, onPress }) => {
      const [clickedBtn, setIsClicked] = useState(null);
    
      React.useEffect(() => {
        console.log(clickedBtn);
      }, [clickedBtn]);
    
      return (
        <View style={[styles.container, contentStyle]}>
          <TouchableOpacity
            style={[
              styles.btn,
              styles.left,
              clickedBtn == 1 && styles.backgroundColor,
            ]}
            onPress={() => setIsClicked(1)}>
            <Text
              style={[styles.btnTextStyle, clickedBtn == 1 && styles.textColor]}>
              firstBtn
            </Text>
          </TouchableOpacity>
          <TouchableOpacity
            style={[
              styles.btn,
              styles.right,
              clickedBtn == 2 && styles.backgroundColor,
            ]}
            onPress={() => setIsClicked(2)}>
            <Text
              style={[styles.btnTextStyle, clickedBtn == 2 && styles.textColor]}>
              secondBtn
            </Text>
          </TouchableOpacity>
        </View>
      );
    };
    
    RoundedButtons.propTypes = {
      firstBtn: Text.propTypes,
      secondBtn: Text.propTypes,
    };
    
    export default RoundedButtons;