skip to Main Content

I am trying to implement a Switch component in react native but the switch different in the android platform. I did explore a lot but I didn’t find any references finally i found but it is in type script and a class-based component can someone help me to convert in JSX and functional-based component?

import * as React from 'react';
import {
  Animated,
  Easing,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';

interface Props {
  onColor: string;
  offColor: string;
  label: string;
  onToggle: () => void;
  style: object;
  isOn: boolean;
  labelStyle: object;
}

interface DefaultProps {
  onColor: string;
  offColor: string;
  label: string;
  onToggle: () => void;
  style: object;
  isOn: boolean;
  labelStyle: object;
}

export default class Toggle extends React.PureComponent<Props> {
  animatedValue = new Animated.Value(0);

  static defaultProps: DefaultProps = {
    onColor: '#4cd137',
    offColor: '#ecf0f1',
    label: '',
    onToggle: () => {},
    style: {},
    isOn: false,
    labelStyle: {},
  };

  render() {
    const moveToggle = this.animatedValue.interpolate({
      inputRange: [0, 1],
      outputRange: [0, 20],
    });

    const {
      isOn,
      onColor,
      offColor,
      style,
      onToggle,
      labelStyle,
      label,
    } = this.props;

    const color = isOn ? onColor : offColor;

    this.animatedValue.setValue(isOn ? 0 : 1);

    Animated.timing(this.animatedValue, {
      toValue: isOn ? 1 : 0,
      duration: 300,
      easing: Easing.linear,
    }).start();

    return (
      <View style={styles.container}>
        {!!label && <Text style={[styles.label, labelStyle]}>{label}</Text>}

        <TouchableOpacity
          onPress={() => {
            typeof onToggle === 'function' && onToggle();
          }}>
          <View
            style={[styles.toggleContainer, style, { backgroundColor: color }]}>
            <Animated.View
              style={[
                styles.toggleWheelStyle,
                {
                  marginLeft: moveToggle,
                },
              ]}
            />
          </View>
        </TouchableOpacity>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  toggleContainer: {
    width: 50,
    height: 30,
    marginLeft: 3,
    borderRadius: 15,
    justifyContent: 'center',
  },
  label: {
    marginRight: 2,
  },
  toggleWheelStyle: {
    width: 25,
    height: 25,
    backgroundColor: 'white',
    borderRadius: 12.5,
    shadowColor: '#000',
    shadowOffset: {
      width: 0,
      height: 2,
    },
    shadowOpacity: 0.2,
    shadowRadius: 2.5,
    elevation: 1.5,
  },
});

2

Answers


  1. Basically, as a functional component in jsx, the above would translate to:

    import * as React from 'react';
    import {
      Animated,
      Easing,
      StyleSheet,
      Text,
      TouchableOpacity,
      View,
    } from 'react-native';
    import PropTypes from 'prop-types';
    
    const Toggle = props => {
      const animatedValue = new Animated.Value(0);
    
      const moveToggle = animatedValue.interpolate({
        inputRange: [0, 1],
        outputRange: [0, 20],
      });
    
      const {isOn, onColor, offColor, style, onToggle, labelStyle, label} = props;
    
      const color = isOn ? onColor : offColor;
    
      animatedValue.setValue(isOn ? 0 : 1);
    
      Animated.timing(animatedValue, {
        toValue: isOn ? 1 : 0,
        duration: 300,
        easing: Easing.linear,
        useNativeDriver: false,
      }).start();
    
      return (
        <View style={styles.container}>
          {!!label && <Text style={[styles.label, labelStyle]}>{label}</Text>}
    
          <TouchableOpacity onPress={typeof onToggle === 'function' && onToggle}>
            <View style={[styles.toggleContainer, style, {backgroundColor: color}]}>
              <Animated.View
                style={[
                  styles.toggleWheelStyle,
                  {
                    marginLeft: moveToggle,
                  },
                ]}
              />
            </View>
          </TouchableOpacity>
        </View>
      );
    };
    
    Toggle.propTypes = {
      onColor: PropTypes.string,
      offColor: PropTypes.string,
      label: PropTypes.string,
      onToggle: PropTypes.func,
      style: PropTypes.object,
      isOn: PropTypes.bool.isRequired,
      labelStyle: PropTypes.object,
    };
    
    Toggle.defaultProps = {
      onColor: '#4cd137',
      offColor: '#ecf0f1',
      label: '',
      onToggle: () => {},
      style: {},
      isOn: false,
      labelStyle: {},
    };
    
    export default Toggle;
    
    const styles = StyleSheet.create({
      container: {
        flexDirection: 'row',
        alignItems: 'center',
      },
      toggleContainer: {
        width: 50,
        height: 30,
        marginLeft: 3,
        borderRadius: 15,
        justifyContent: 'center',
      },
      label: {
        marginRight: 2,
      },
      toggleWheelStyle: {
        width: 25,
        height: 25,
        backgroundColor: 'white',
        borderRadius: 12.5,
        shadowColor: '#000',
        shadowOffset: {
          width: 0,
          height: 2,
        },
        shadowOpacity: 0.2,
        shadowRadius: 2.5,
        elevation: 1.5,
      },
    });
    

    USAGE:

    import React, {useState} from 'react';
    import {View} from 'react-native';
    import Toggle from '..path/to/toggle';
    
    const Screen = () => {
      const [toggleIsOn, setToggle] = useState(false);
      return (
        <View>
          <Toggle
            isOn={toggleIsOn}
            onToggle={() => {
              setToggle(!toggleIsOn);
            }}
          />
        </View>
      );
    };
    
    export default Screen;
    

    You would need to install prop-types (yarn install prop-types) so you can specify types or use flow because js out of the box isn’t type safe.

    Login or Signup to reply.
  2. Switch button with typescript

    import React, {useEffect, useState} from 'react';
    import {Animated, Easing, StyleSheet, Text, TouchableOpacity, View} from 
    'react-native';
    import theme from '@/constants/themeConstants';
    
    type TProps = {
        value: boolean;
        onChange: () => void;
        onColor?: string;
        offColor?: string;
        label?: string;
        labelStyle?: any;
    };
    
    const Switch: React.FC<TProps> = ({
        value,
        onChange,
        onColor = 'green',
        offColor = 'grey',
        label = '',
        labelStyle,
    }) => {
        const [isEnabled, setIsEnabled] = useState(false);
    
        useEffect(() => {
            value && setIsEnabled(value);
        }, [value]);
    
        const toggleSwitch = () => {
            setIsEnabled(!isEnabled);
            onChange();
        };
    
        const animatedValue = new Animated.Value(0);
    
        const moveToggle = animatedValue.interpolate({
            inputRange: [-0.2, 0.9],
            outputRange: [0, 20],
        });
    
        const color = value ? onColor : offColor;
    
        animatedValue.setValue(value ? 0 : 1);
    
        Animated.timing(animatedValue, {
            toValue: value ? 1 : 0,
            duration: 300,
            easing: Easing.linear,
            useNativeDriver: false,
        }).start();
    
        return (
            <View style={styles.container}>
                {!!label && <Text style={[styles.label, labelStyle]}>{label} 
            </Text>}
    
            <TouchableOpacity onPress={toggleSwitch} activeOpacity={1}>
                <View style={[styles.toggleContainer, {backgroundColor: 
                 color}]}>
                    <Animated.View style={[styles.toggleWheelStyle, 
    {marginLeft: moveToggle}]} />
                    </View>
                </TouchableOpacity>
            </View>
        );
    };
    

    export default Switch;

    const styles = StyleSheet.create({
        container: {
            flexDirection: 'row',
            alignItems: 'center',
        },
        toggleContainer: {
            width: 50,
            height: 30,
            marginLeft: 3,
            borderRadius: 15,
            justifyContent: 'center',
        },
        label: {
            marginRight: 2,
        },
        toggleWheelStyle: {
            width: 25,
            height: 25,
            backgroundColor: 'white',
            borderRadius: 12.5,
            shadowColor: '#000',
            shadowOffset: {
                width: 0,
                height: 2,
            },
            shadowOpacity: 0.2,
            shadowRadius: 2.5,
            elevation: 1.5,
        },
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search