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
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.
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
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.
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 = () => { /*...*/ }
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!