Style React Native switch component - react-native

I'm developing a mobile application using React Native. This project needs a custom button to provides a boolean type of input. But I have no idea how to create this kind of custom component for that. I did a research and I try to create this custom button with a react-native switch (import { Switch } from 'react-native';). But seems like It is difficult to style.
I'm not sure what would be the best way to achieve that? Using the switch component? Please help me to find a better solution or new approach for this.
Thank you.

I have made a custom switch in react native and You can do the styling in it a source code is given below -
import React from 'react'
import { Text, TouchableOpacity } from 'react-native'
import styled from 'styled-components/native'
class App extends React.Component {
state = {
active: false
}
handleOFF = () => {
this.setState({
active: false
});
}
handleOn = () => {
this.setState({
active: true
});
}
render() {
return (
<MainView>
<Label>
<LabelOff onPress={this.handleOFF} active={this.state.active} activeOpacity={0.8}>
<Off>OFF</Off>
</LabelOff>
<LabelOn onPress={this.handleOn} active={this.state.active} activeOpacity={0.8}>
<On>ON</On>
</LabelOn>
</Label>
</MainView>
)
}
}
const MainView = styled.View`
margin:50px;
`
const Label = styled.View`
height:60px;
width:240px;
flex-direction:row;
justify-content:space-around;
align-items:center;
background-color:transparent;
`
const LabelOff = styled.TouchableOpacity`
height:60px;
width:120px;
background-color:${props => props.active ? 'transparent' : '#cb6161'};
border:2px solid #cb6161;
border-right-width:0px;
align-items:center;
justify-content:space-around;
`
const LabelOn = styled.TouchableOpacity`
height:60px;
width:120px;
background-color:${props => props.active ? '#55acee' : 'transparent'};
border:2px solid #55acee;
border-left-width:0px;
align-items:center;
justify-content:space-around;
`
const Off = styled.Text`
font-size:22px;
`
const On = styled.Text`
font-size:22px;
`
export default App
Custom switch is done !

Related

How can I change text color of dropdown after switching to/from dark mode. The change is happening after restarting the application

I want the text color of the dropdown to change just after switching to/from dark mode. My code is changing the color of the text by switching to/from dark mode but for that, I have to restart the application. I want this to happen without restarting the application.
import React, { useState, useRef, useEffect } from 'react'
import { Picker } from '#react-native-picker/picker'
import { CgView } from './CgView'
import { CgText } from './CgText'
import Colors from '../Theme/Colors'
import { Appearance } from 'react-native'
const colorScheme = Appearance.getColorScheme();
const MonthtPicker = props => {
const { selectedMonth, onMonthChange } = props
const monthRef = useRef()
const dayRef = useRef()
const [textColor, setTextColor] = useState(Colors.commonTextColor)
useEffect(()=> {
const changeMode = () =>{
if (colorScheme === 'dark') {
// Use dark color scheme
setTextColor('white')
}
else{
setTextColor(Colors.commonTextColor)
}
}
changeMode()
}, [colorScheme])
return (
<CgView>
<CgText bdayLabel>Birthday</CgText>
<CgView row>
<CgView pickerContainer>
<Picker
ref={monthRef}
selectedValue={selectedMonth}
onValueChange={onMonthChange}
dropdownIconColor={Colors.commonTextColor}
itemStyle={{ color: Colors.commonTextColor }}
style={{ color: Colors.commonTextColor }}>
<Picker.Item
label='Select month'
value=' '
color={textColor}
/>
<Picker.Item
label='January'
value='January'
color={textColor}
/>
<Picker.Item
label='February'
value='February'
color={textColor}
/>
<Picker.Item
label='March'
value='March'
color={textColor}
/>
</Picker>
</CgView>
}
export default MonthPicker
Please explain me why my code is not working as expected and try to provide solution using useEffect.
Thank you in advance.

i18next how to use the Trans component in React Native

How to apply a bold weight to certain parts of the translation using the Trans component in React Native?
Since HTML tags like <strong></strong> don't work, we have to create our own custom <Strong/> component that applies certain text styling to the translation, but I don't know how to do that despite reading the docs?
Docs:
import { Trans } from 'react-i18next';
function MyComponent({ person, messages }) {
const { name } = person;
const count = messages.length;
return (
<Trans i18nKey="userMessagesUnread" count={count}>
Hello <strong title={t('nameTitle')}>{{name}}</strong>, you have {{count}} unread message. <Link to="/msgs">Go to messages</Link>.
</Trans>
);
}
i guess you can use <Text style={{fontWeight: 'bold'}}>{{name}}</Text> instead of <strong title={t('nameTitle')}>{{name}}</strong>.
or using useTranslation
import React from 'react';
import { useTranslation } from 'react-i18next';
export function MyComponent() {
const { t, i18n } = useTranslation();
// or const [t, i18n] = useTranslation();
return <Text style={{fontWeight: 'bold'}}>{t('my translated text')}</Text>
}
don't test yet

use React Hook in multi files?

Senario : I have a dialog, and i use a react-hook to make it disappear ,like const[show,setShow]= useState(false) , this dialog file is a seperate file with main screen file, which contain button to show this dialog
Problem : I don't know how to show this dialog in main screen, for example, my dialog file called Mydialog.js have componet Mydialog, so i tried to put that hook show in props , Mydialog(show), but look like it not work that way, i still can't show the dialog
Question. How can i use react-hook for multi file, like i have hook in dialog file, present the dialog status ( show or not) then i can use it in mainScreen file to set show to true, then i can use that show and set to false when click button in dialog
If I understood it right you're trying to bring up a dialog when you interact with something on the main page and then close it by clicking on the X within the dialog. Would something like this work?
Main.js:
import "./styles.css";
import { useState } from "react";
import MyDialog from "./MyDialog";
export default function App() {
const [showDialog, setShowDialog] = useState(false);
const handleDialog = () => {
setShowDialog(!showDialog);
};
return (
<>
<button onClick={handleDialog}>Show Dialog</button>
Show Dialog: {showDialog?.toString()}
{showDialog && <MyDialog handleDialog={handleDialog} />}
</>
);
}
MyDialog.js:
import "./styles.css";
export default function MyDialog({ handleDialog }) {
return (
<>
<div className="popup">
<div className="popup_open">
<h1>Dialog Content</h1>
<button onClick={handleDialog}>X</button>
</div>
</div>
</>
);
}
Sandbox link if you want to test: https://codesandbox.io/s/admiring-feather-sy1gf
You can use Context to maintain state between multiple components.
const DialogContext = createContext();
const DialogProvider = ({ children }) => {
const [isDialogVisible, setDialogVisible] = useState(false);
const value = {
isDialogVisible,
setDialogVisible,
}
return <DialogContext.Provider value={value}>{children}</DialogContext.Provider>
}
const useDialog = () => {
const context = useContext(DialogContext);
return context;
}
Render the DialogProvider in one of the top-level components, for example in App.js.
// App.js
return (
<DialogProvider>
// ...
</DialogProvider>
)
Then inside of your components you can use your hook and trigger the visibility of the dialog.
MyComponentA:
const { isDialogVisible, setDialogVisible } = useDialog();
const toggleDialogVisibility = () => {
setDialogVisible(!isDialogVisible);
}
return (
<Button title="Toggle" onPress={toggleDialogVisibility} />
)
MyComponentB:
const { isDialogVisible } = useDialog();
if(isDialogVisible) {
return <Text>My Dialog</Text>
}
return null;
A very simple example of usage, here's a Snack for the above.

How do I create a global component without injection?

There is a case that we need a component in global to use it like this.$toast('some words') or this.$dialog({title:'title words',contentText:'some words').
In Vue 2.x, we can add Toast.vue's methods to Vue.prototype, and call Toast.vue's methods everywhere. But how do we do this in Vue 3.x?
I read the document of i18n plugin demo in vue-next. But it needs to inject the i18n plugin into every component that needs to use it. It's not convenient.
A way showing the component anywhere in vue3 app without injection
mechanism
mountting the component into dom each time.
implementation
use 'Toast' for example:
step 1: create a SFC (Toast.vue)
<template>
<transition name="fade">
<div class="toast" v-html="msg" :style="style" #click="closeHandle"></div>
</transition>
</template>
<script>
import {ref,computed,onMounted,onUnmounted} from 'vue'
export default {
name: "Toast",
props:{
msg:{type:String,required:true},
backgroundColor:{type:String},
color:{type:String},
// closing the Toast when timed out. 0:not closed until to call this.$closeToast()
timeout:{type:Number,default:2000, validate:function (val){return val >= 0}},
// closing the Toast immediately by click it, not wait the timed out.
clickToClose:{type:Boolean, default: true},
// a function provied by ToastPlugin.js, to unmout the toast.
close:{type:Function,required: true}
},
setup(props){
let innerTimeout = ref();
const style = computed(
()=>{return{backgroundColor:props.backgroundColor ? props.backgroundColor : '#696969', color:props.color ? props.color : '#FFFFFF'}}
);
onMounted(()=>{
toClearTimeout();
if(props.timeout > 0)
innerTimeout.value = setTimeout(()=>{ props.close(); },props.timeout);
});
/**
* when toast be unmounted, clear the 'innerTimeout'
*/
onUnmounted(()=>{toClearTimeout()})
/**
* unmount the toast
*/
const closeHandle = () => {
if(props.clickToClose)
props.close();
}
/**
* to clear the 'innerTimeout' if it exists.
*/
const toClearTimeout = ()=>{
if(innerTimeout.value){
try{
clearTimeout(innerTimeout.value);
}catch (e){
console.error(e);
}
}
}
return {style,closeHandle};
},
}
</script>
<style scoped>
.toast{position: fixed; top: 50%; left: 50%; padding: .3rem .8rem .3rem .8rem; transform: translate(-50%,-50%); z-index: 99999;
border-radius: 2px; text-align: center; font-size: .8rem; letter-spacing: .1rem;}
.fade-enter-active{transition: opacity .1s;}
.fade-leave-active {transition: opacity .3s;}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {opacity: 0;}
</style>
step 2: create a plugin (ToastPlugin.js)
import Toast from "./Toast.vue";
import {createApp} from 'vue'
const install = (app) => {
// dom container for mount the Toast.vue
let container;
// like 'app' just for Toast.vue
let toastApp;
// 'props' that Toast.vue required.
const baseProps = {
// define a function to close(unmount) the toast used for
// case 1: in Toast.vue "click toast appeared and close it"
// case 2: call 'this.$closeToast()' to close the toast in anywhere outside Toast.vue
close:()=> {
if (toastApp)
toastApp.unmount(container);
container = document.querySelector('#ToastPlug');
if(container)
document.body.removeChild(container);
}
};
// show Toast
const toast = (msg)=>{
if(typeof msg === 'string')
msg = {msg};
const props = {...baseProps,...msg}
console.log('props:',JSON.stringify(props));
// assume the toast(previous) was not closed, and try to close it.
props.close();
// create a dom container and mount th Toast.vue
container = document.createElement('div');
container.setAttribute('id','ToastPlug');
document.body.appendChild(container);
toastApp = createApp(Toast, props);
toastApp.mount(container);
}
// set 'toast()' and 'close()' globally
app.config.globalProperties.$toast = toast;
app.config.globalProperties.$closeToast = baseProps.close;
}
export default install;
step 3: usage
in main.js
import ToastPlugin from 'xxx/ToastPlugin'
import { createApp } from 'vue'
const app = createApp({})
app.use(ToastPlugin)
// then the toast can be used in anywhere like this:
this.$toast('some words')
this.$toast({msg:'some words',timeout:3000})
Vue 3 provides an API for attaching global properties:
import { createApp } from 'vue'
const app = createApp({})
app.config.globalProperties.$toast = () => { /*...*/ }

Using a class as props in a react native component

I'm learning react (coming from a native iOS/Swift background) and I'm a bit confused about something I can't get to work.
I have a component that accepts props, so I figured I would write a class to model those props:
class HeaderProps {
text: string;
constructor(headerText:string) {
this.text = headerText;
}
}
// Make a component
const Header = (props:HeaderProps) => {
const { textStyle, viewStyle } = styles;
return (
<View style={viewStyle}>
<Text style={textStyle}>{props.text}</Text>
</View>
);
};
and I'm exporting from my component like so:
export {Header, HeaderProps};
I'm then importing it:
import {Header, HeaderProps} from './src/components/header';
// Create a component
const App = () => ( <Header headerText={ new HeaderProps('Album') } />);
No text is appearing in my component.
If I just pass a string through as props it works fine, can't think of any reason why sending a class through wouldn't work.
I'm using flow type to declare the types of my arguments, not sure if that might be causing any issues.
A point in the right direction would be much appreciated!