Simple word memorization app with React Native + Realm + Zustand
Introduction
Hello. I am sharing this post to share a simple application that I developed for my lack of English words and to give a short example about the use of Realm, Zustand. I made this application on “Preply” of my teacher Fabian Afumbom A., which he used while learning a language, during the periods when I was taking lessons in the Preply application. Well, without further ado, let’s get to the point.
Packages Used
Package Installations (React native v0.64.2)
First, we open our project in terminal and create it with react native.
npx react-native init FabianEnglish
you can replace “FabianEnglish” with a project name of your choice.
Then we proceed to the project directory
cd FabianEnglish
and we install realm
npm install realm
then we install the pods
cd ios && pod install && cd ..
that’s it for realm.
It’s time to install zustand. If you are sure that you are in the root directory, paste the code below into the terminal again and complete the zustand installation.
npm install zustand
or with yarn
yarn add zustand
it’s time to install react native vector icons. Icons are always needed so that the project looks a little better :). Let’s add our package.
npm install --save react-native-vector-icons
Finally, let’s add our blur package
yarn add @react-native-community/blur
or
npm install --save @react-native-community/blur
and finally, let’s install the pods for ios
cd ios && pod install && cd ..
paket kurulumu tamamlandı.
This Project’s GitHub page
https://github.com/HanzalaGun/FabianEnglish
Let’s Code the Project
First, let’s create our folders to split the project into parts. We create a folder named src in the root directory and 4 folders named common, components, screen, state under this folder. Then we create a file named ListScreen.js in the screen.
we can write this file’s code directly in App.js. Awe can show this file directly in App.js. Actually, for more complex structures, we could code what we would code directly into App.js , but if we want to grow the project in the future and the pages increase, let’s keep our structure ready so that there is no confusion :). App.js will look like this.
import React from 'react'
import ListScreen from './src/screens/ListScreen'
const App = () => {
return (
<ListScreen/>
)
}
export default App
artık ListScreen.js eNow we can move on to ListScreen.js. First of all, I wanted to give a background photo and a blur in front of this photo. For this, we put a background photo we want in the common folder with the name bg.jpg. this name is not important, just make sure it has the same name when you import the picture. for import this picture we can use this code
const bg= require('../common/bg.jpg')
We transfer it to ListScreen.js with. Let’s import our icons
import Icon from 'react-native-vector-icons/FontAwesome';
and to use this icon
Icon.loadFont()
We need to load the icons by typing the above code snippet into the page. In the meantime, let’s prepare a small component for the blur background. We create a file called MyBlur.js in components and use our “@react-native-community/blur” plugin here. Our MyBlur.js file looks like this
import React from 'react'
import { StyleSheet } from 'react-native'
import { BlurView } from "@react-native-community/blur";
const MyBlur = () => {
return (
<BlurView
style={styles.absolute}
blurType="dark"
/>
)
}
export default MyBlur
const styles = StyleSheet.create({
absolute: {
position: "absolute",
top: 0,
left: 0,
bottom: 0,
right: 0,
}
})
Let’s go back to our ListScreen.js page. On this page, FabianEnglish will be written on the left in the header section. On the right, there will be two buttons, one of which will be “Ask Me” and the other will be “Learn”. There will be a modal where we will translate the word that we recorded for us with Ask Me, and if it is correct, the score of the word will increase. There will be a skip button under it and if we press this button, the score will decrease. There will be a search input under the header so that we can search for words. Then there will be a button that we position as absolute at the bottom right, when we press this button, the section where we can save the word will become visible. Finally, our words will be listed in the body section. Before we forget, let’s create a TextInput of our own. So first go to the components folder
- Askme.js
- Learn.js
- SendComp.js(the component we will save the word)
- ListComp.js(component to list words )
- MyTextInput.js
We create this pages.
Finally, let’s create our state management without going back to ListScreen.
I created a file named state.js in our state folder. Yes, let’s start using Zustand, which is one of the main topics. Here we can say that we create our state and actions. But it was much easier to use than redux :). Let’s first share the codes in state.js and then try to explain.
import create from 'zustand'
export const useStore = create(set => ({
wordState:false,
popupState:false,
askmeState:false,
learnState:false,
selectedWordState:{},
search:"",
setWordState:(data)=>set((state)=>({...state,wordState:data})),
setPopupState:(data)=>set((state)=>({...state,popupState:data})),
setAskmeState:(data)=>set((state)=>({...state,askmeState:data})),
setLearnState:(data)=>set((state)=>({...state,learnState:data})),
setSelectedWordState:(data)=>set((state)=>({...state,selectedWordState:data})),
setSearch:(data)=>set((state)=>({...state,search:data})),
}))
Firstly,
First, we call the create function from zustand, assign this function to a variable named useStore, export it and create an array function with the set parameter in our create function. and we define our variables such as wordState, learnState, search as variables. We value it as necessary, such as object, string, int, boolean.. We can say that our variables that start with the set prefix are our actions, we will use them to update the states we have defined above. For more, you can dive into zustand’s documentation :).
but to read state basicly
const loading = useStore(state => state.wordState)
for update the state
const setLoading = useStore(state => state.setWordState)
we can use this.
Yes, now we are finishing ListScreen.js and we are writing it like this.
import React from 'react'
import { StyleSheet, Text, SafeAreaView, View, Pressable, ImageBackground } from 'react-native'
import Icon from 'react-native-vector-icons/FontAwesome';
import AskMe from '../components/AskMe';
import Learn from '../components/Learn';
import ListComp from '../components/ListComp'
import SendComp from '../components/SendComp'
import MyTextInput from '../components/MyTextInput'
import { useStore } from '../state/atom';
import MyBlur from '../components/MyBlur';
const bg= require('../common/bg.jpg')
Icon.loadFont()
const ListScreen = () => {
const setAskVisible = useStore(state => state.setAskmeState)
const setLearnVisible = useStore(state => state.setLearnState)
const setSearch = useStore(state => state.setSearch)
const search=(data)=>{
setSearch(data)
}
return (
<ImageBackground
source={bg}
resizeMode="stretch"
style={{backgroundColor:'white'}}
>
<MyBlur/>
<View style={styles.head1}>
<SafeAreaView>
<View style={styles.head}>
<Text style={styles.title}>Fabian English |</Text>
<Pressable style={styles.pressable}
onPress={()=>setAskVisible(true)}>
<Icon size={30} name="question" color="white" style={styles.pressableicon}></Icon>
<Text style={styles.headtext}>ask me</Text>
</Pressable>
<Pressable style={styles.pressable}
onPress={()=>setLearnVisible()}>
<Icon size={30} name="book" color="white" style={styles.pressableicon}></Icon>
<Text style={styles.headtext}>learn</Text>
</Pressable>
</View>
</SafeAreaView>
</View>
<AskMe/>
<Learn/>
<SafeAreaView style={styles.container}>
<View>
<MyTextInput placeholder="Search" onChange={(data)=>search(data)} padding={20}/>
</View>
<ListComp/>
</SafeAreaView>
<SendComp/>
</ImageBackground>
)
}
export default ListScreen
const styles = StyleSheet.create({
container:{
height:'100%',
},
head:{
flexDirection:'row',
justifyContent:'space-around',
marginBottom:10,
alignItems:'center',
paddingVertical:10,
},
head1:{
marginBottom:10,
backgroundColor:'#ffffff50',
shadowColor:'black',
shadowOpacity:0.,
shadowRadius:1,
shadowOffset:{width: -1, height: 3},
},
title:{
color:'white',
fontSize:20,
fontWeight:'700',
textShadowColor:'black',
textShadowRadius:3,
textShadowOffset:{width: -1, height: 1},
},
headtext:{
color:'white',
fontSize:14,
fontWeight:'600',
textShadowColor:'black',
textShadowRadius:6,
textShadowOffset:{width: -1, height: 1},
paddingLeft:3
},
pressable:{
flexDirection:'row',
alignItems:'center'
},
pressableicon:{
shadowColor:'black',
shadowOpacity:0.2,
shadowRadius:1,
shadowOffset:{width: -1, height: 3},
},
})
useStore ile zustand a nasıl veri gönderebileceğimizi görmüşsündür, bu kadar kYou have seen how we can send data to a zustand with useStore, it’s that easy 🙂
Let’s share the other components in turn.
//MyTextInput.js
import React from 'react'
import { StyleSheet, View, TextInput, Dimensions } from 'react-native'
const MyTextInput = ({onChange,placeholder,value,autoFocus=false,padding=70}) => {
return (
<View style={[styles.container,{width:Dimensions.get('screen').width-padding}]}>
<TextInput style={{paddingVertical:5}} autoFocus={autoFocus} value={value} placeholder={placeholder} placeholderTextColor='white' onChangeText={(a)=>{onChange(a)}}></TextInput>
</View>
)
}
export default MyTextInput
const styles = StyleSheet.create({
container:{
backgroundColor:'#f2f2f270',
padding:5,
margin:3,
alignSelf:'center',
borderRadius:5,
}
})
Let’s take a look at the important issue, Realm, which intervenes here.
import Realm from 'realm'
To use it, we need to import it as above. And we need to use a schema. Since we will use this scheme in a different way, let’s put it in a separate file for a cleaner look and ease of use. Let’s create a Shema.js file in our public folder.
export const WordShema = {
name: 'Words',
properties: {
id:'int',
name: 'string',
description: 'string',
pronunciation: 'string',
translate: 'string',
date: 'date',
score: 'int'
}
};
We don’t have much to tell in this. First “name” is our shema’s name . Other keys are our datas veriable in the properties.
- id => identical id
- name => our word what we want to learn
- description => if we want to add a description at our word
- pronunciation => pronuncitation
- translate => translated word
- date => data’s created date
- score => the word’s score
let’s go to usage
import { WordShema } from '../common/Shema';
we import our shema
öncelikleFirst of all, we tell which scheme we will open using the realmi function opening function, and after opening it, we write what we do.
Realm.open({schema:[WordShema]}).then(realm=>{
//we are always use this area .
})
For example we want to get all datas
Realm.open({schema:[WordShema]}).then(realm=>{
let obj = realm.objects('Words');
})
İf we want to write a data to our database
Realm.open({schema:[WordShema]}).then(realm=>{
realm.write(()=>{
const myData=realm.create('Words',{
id:'benzersiz id',
name:'kelime',
description:'açıklama',
pronunciation:'telafuz',
translate:'çeviri',
date:new Date(),
score:0
})
})
})
we can use this.
or update a data in realm,
Realm.open({schema:[WordShema]}).then(realm=>{
let obj = realm.objects('Words').filtered("id='"+data.id+"'")[0];
realm.write(() => {
obj.name='güncellenen kelime'
})
})
we can use this.
Now that we see the use of realm as a basis, we can return to our codes. Let’s continue with the components and even though I share them all one after the other, there is no part you can’t understand :). I don’t need any further explanation 🙂
//SendComp.js
import React, {useState, useEffect} from 'react'
import { StyleSheet, Text, View, TouchableOpacity, Dimensions, Alert, SafeAreaView } from 'react-native'
import MyTextInput from './MyTextInput'
import Realm from 'realm';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import { useStore } from '../state/state';
import { WordShema } from '../common/Shema';
const width=Dimensions.get('screen').width;
Icon.loadFont()
const SendComp = ({isSend=true}) => {
const data = useStore(state => state.selectedWordState)
const [name, setName] = useState('')
const [description, setDescription] = useState('')
const [pronunciation, setPronunciation] = useState('')
const [translate, setTranslate] = useState('')
const [opened, setOpened] = useState(isSend?false:true)
const setLoading = useStore(state => state.setWordState)
const setModalVisible = useStore(state => state.setPopupState)
useEffect(() => {
if(!isSend&&data){
setName(data.name)
setDescription(data.description)
setPronunciation(data.pronunciation)
setTranslate(data.translate)
}
}, [data])
const sendData=()=>{
if(name.length>0&&translate.length>0){
Realm.open({schema:[WordShema]}).then(realm=>{
realm.write(()=>{
const myData=realm.create('Words',{
id:parseInt(new Date().getTime()+''+Math.floor(Math.random()*10000)),
name:name,
description:description,
pronunciation:pronunciation,
translate:translate,
date:new Date(),
score:0
})
})
}).then(()=>{
setLoading(true)
setName('')
setDescription('')
setPronunciation('')
setTranslate('')
setModalVisible(false)
})
}else{
Alert.alert('You must be fill Word and Translate')
}
}
const updateData = ()=>{
if(name.length>0&&translate.length>0){
Realm.open({schema:[WordShema]}).then(realm=>{
let obj = realm.objects('Words').filtered("id='"+data.id+"'")[0];
realm.write(() => {
obj.name=name
obj.description=description
obj.pronunciation=pronunciation
obj.translate=translate
})
}).then(()=>{
setLoading(true)
setModalVisible(false)
})
}else{
Alert.alert('You must be fill Word and Translate')
}
}
return (
<SafeAreaView style={[styles.container,isSend?{position:'absolute',
bottom:150,
left:10}:null]}>
{opened&&<View style={styles.inputs}>
<MyTextInput value={name} placeholder='Word' onChange={(data)=>{setName(data)}}></MyTextInput>
<MyTextInput value={translate} placeholder='Translate' onChange={(data)=>{setTranslate(data)}}></MyTextInput>
<MyTextInput value={pronunciation} placeholder='Pronunciation' onChange={(data)=>{setPronunciation(data)}}></MyTextInput>
<MyTextInput value={description} placeholder='Description' onChange={(data)=>{setDescription(data)}}></MyTextInput>
</View>}
<View>
{opened?
<View style={{flex:1}}>
<TouchableOpacity style={styles.buttonsend} onPress={()=>isSend?sendData():updateData()}>
<Icon name={isSend?"send":'update'} size={isSend?30:50} color="green" />
</TouchableOpacity>
{isSend&&<TouchableOpacity style={styles.buttonminus} onPress={()=>setOpened(false)}>
<Icon name="minus" size={30} color="red" />
</TouchableOpacity>}
</View>
:
<View style={{alignItems:'flex-end', width:width-35,}}>
<TouchableOpacity style={styles.buttonplus} onPress={()=>setOpened(true)}>
<Icon style={styles.plusicon} name="plus" size={30} color="white" />
</TouchableOpacity>
</View>
}
</View>
</SafeAreaView>
)
}
export default SendComp
const styles = StyleSheet.create({
container:{
flexDirection:'row',
paddingHorizontal:10,
},
buttonplus:{
backgroundColor:'#fff5',
padding:10,
borderRadius:50,
borderWidth:1,
borderColor:'white',
shadowColor:'black',
shadowOpacity:0.5,
shadowRadius:1,
shadowOffset:{width: -1, height: 3},
},
buttonminus:{
position:'absolute',
bottom:-10
},
buttonsend:{
justifyContent:'center',
flex:1,
},
plusicon:{
shadowColor:'black',
shadowOpacity:0.5,
shadowRadius:1,
shadowOffset:{width: -1, height: 3},
},
inputs:{
backgroundColor:'#111',
borderRadius:5
}
})
//Askme.js
import React, { useEffect, useState } from 'react'
import { StyleSheet, Dimensions, View,Modal, TouchableOpacity, Text } from 'react-native'
import Realm from 'realm'
import { useStore } from '../state/atom';
import { WordShema } from '../common/Shema';
import MyTextInput from './MyTextInput';
import MyBlur from './MyBlur';
const AskMe = () => {
const visible = useStore(state => state.askmeState)
const setVisible = useStore(state => state.setAskmeState)
const [data, setData] = useState([])
const [word, setWord] = useState('')
const [index, setIndex] = useState(0)
useEffect(() => {
Realm.open({schema:[WordShema]}).then(realm=>{
setData(realm.objects('Words').sorted('score',true))
})
}, [])
useEffect(() => {
if(data.length>0&&word.toLowerCase()==data[index].translate.toLowerCase()){
//realmda kelimenin scorunu yükselt
Realm.open({schema:[WordShema]}).then(realm=>{
let obj = realm.objects('Words').filtered("id='"+data[index].id+"'")[0];
realm.write(() => {
obj.score++
})
}).then(()=>{
setIndex(data.length!=index+1?index+1:0)
setWord('')
})
}
}, [word])
const skip =()=>{
//realmda kelimenin scorunu düşür
if(data.length>0){
Realm.open({schema:[WordShema]}).then(realm=>{
let obj = realm.objects('Words').filtered("id='"+data[index].id+"'")[0];
realm.write(() => {
obj.score--
})
console.log(obj)
}).then(()=>{
setIndex(data.length!=index+1?index+1:0)
setWord('')
})
}
}
return (
<Modal
animationType='slide'
transparent={true}
visible={visible}
>
<MyBlur/>
<TouchableOpacity style={styles.view} onPress={()=>setVisible(false)}>
<Text style={styles.title}>{data.length>0&&data[index].name}</Text>
<Text style={styles.text}>{data.length>0&&'( '+data[index].pronunciation+' )'}</Text>
<Text style={styles.text}>{data.length>0&&data[index].description}</Text>
<MyTextInput
value={word}
autoFocus placeholder="Write Translate"
onChange={(data)=>{setWord(data)}}
></MyTextInput>
<TouchableOpacity style={styles.skip} onPress={()=>skip()}>
<Text style={styles.skiptext}>{'skip >>'}</Text>
</TouchableOpacity>
<View style={{height:40}}/>
<Text style={styles.bottom}>if you skip this word, the word's score to less</Text>
<Text style={styles.bottom}>if you learned this word, you must delete this word</Text>
</TouchableOpacity>
</Modal>
)
}
export default AskMe
const styles = StyleSheet.create({
view:{
width:'100%',
height:'100%',
alignItems:'center',
justifyContent:'center',
alignSelf:'center',
borderRadius:10
},
skiptext:{
color:'white',
fontWeight:'900'
},
skip:{
padding:10,
marginTop:20,
backgroundColor:'#f005',
alignItems:'flex-end',
width:Dimensions.get('screen').width-70,
borderRadius:5
},
title:{
color:'white',
fontSize:25,
fontWeight:'900',
textShadowColor:'#f00',
textShadowRadius:5,
textShadowOffset:{width: 0, height: 0},
marginBottom:20
},
bottom:{
color:'white',
fontSize:12
},
text:{
color:'white'
}
})
//Learn.js
import React, { useEffect, useState } from 'react'
import { StyleSheet, Dimensions, View,Modal, TouchableOpacity, Text } from 'react-native'
import Realm from 'realm'
import { useStore } from '../state/atom';
import { WordShema } from '../common/Shema';
import MyBlur from './MyBlur';
const Learn = () => {
const visible = useStore(state => state.learnState)
const setVisible = useStore(state => state.setLearnState)
const [data, setData] = useState([])
const [index, setIndex] = useState(0)
useEffect(() => {
Realm.open({schema:[WordShema]}).then(realm=>{
setData(realm.objects('Words').sorted('score',true))
})
}, [])
const skip =()=>{
setIndex(data.length!=index+1?index+1:0)
}
return (
<Modal
animationType='slide'
transparent={true}
visible={visible}
>
<MyBlur/>
<TouchableOpacity style={styles.view} onPress={()=>setVisible(false)}>
<Text style={styles.title}>{data.length>0&&data[index].name}</Text>
<Text style={styles.text}>{data.length>0&&'( '+data[index].pronunciation+' )'}</Text>
<Text style={styles.text}>{data.length>0&&data[index].translate}</Text>
<Text style={styles.text}>{data.length>0&&data[index].description}</Text>
<TouchableOpacity style={styles.skip} onPress={()=>skip()}>
<Text style={styles.skiptext}>{'next >>'}</Text>
</TouchableOpacity>
<View style={{height:40}}/>
</TouchableOpacity>
</Modal>
)
}
export default Learn
const styles = StyleSheet.create({
view:{
width:'100%',
height:'100%',
alignItems:'center',
justifyContent:'center',
alignSelf:'center',
borderRadius:10
},
skiptext:{
color:'white',
fontWeight:'900'
},
skip:{
padding:10,
marginTop:20,
backgroundColor:'#f005',
alignItems:'center',
width:Dimensions.get('screen').width-70,
borderRadius:5
},
title:{
color:'white',
fontSize:25,
fontWeight:'900',
textShadowColor:'#f00',
textShadowRadius:5,
textShadowOffset:{width: 0, height: 0},
marginBottom:20
},
text:{
color:'white'
}
})
//ListComp.js
import React, {useState, useEffect} from 'react'
import { View, Dimensions, ScrollView } from 'react-native'
import Realm from 'realm';
import MyRow from './MyRow';
import { useStore } from '../state/state';
import { WordShema } from '../common/Shema';
const height=Dimensions.get('screen').height;
const ListComp = () => {
const [data, setData] = useState([])
const loading = useStore(state => state.wordState)
const search = useStore(state => state.search)
const setLoading = useStore(state => state.setWordState)
const setModalVisible = useStore(state => state.setPopupState)
useEffect(() => {
Realm.open({schema:[WordShema]}).then(realm=>{
setData(realm.objects('Words').sorted('date',true))
}).then(()=>{setLoading(false)
setModalVisible(false)})
}, [loading])
useEffect(() => {
Realm.open({schema:[WordShema]}).then(realm=>{
setData(realm.objects('Words').sorted('date',true))
}).then(()=>{
setModalVisible(false)
})
}, [])
useEffect(() => {
Realm.open({schema:[WordShema]}).then(realm=>{
setData(realm.objects('Words').filtered(
'translate CONTAINS[c] "'+search+'" OR name CONTAINS[c] "'+search+'"'
))
}).then(()=>{setLoading(false)
})
}, [search])
return (
<View key='1' style={{height:height-145}}>
<ScrollView overScrollMode="always">
{data.length>0&&
data.map((data,ind)=>{
return(
<MyRow key={ind} data={data} ind={ind} />
)
})
}
</ScrollView>
</View>
)
}
export default ListComp
Bu komponentler içerisinde kullandığımız diğer komponentleri de burada paylaşabilirim.
//MyModal.js
import React from 'react'
import { StyleSheet, Modal, TouchableOpacity } from 'react-native'
import { useStore } from '../state/atom';
import SendComp from './SendComp';
import MyBlur from './MyBlur';
const MyModal = () => {
const visible = useStore(state => state.popupState)
const setVisible = useStore(state => state.setPopupState)
const setSelectedData = useStore(state => state.setSelectedWordState)
return (
<Modal
animationType='slide'
transparent={true}
visible={visible}
>
<MyBlur/>
<TouchableOpacity style={styles.view} onPress={()=>{
setVisible(false)
setSelectedData({})}}>
<SendComp isSend={false} />
</TouchableOpacity>
</Modal>
)
}
export default MyModal
const styles = StyleSheet.create({
view:{
width:'100%',
height:'100%',
alignItems:'center',
justifyContent:'center',
alignSelf:'center',
borderRadius:10
}
})
//MyRow.js
import React, {useEffect} from 'react'
import { Dimensions, StyleSheet, Text, View, TouchableOpacity } from 'react-native'
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import { WordShema } from '../common/Shema';
import { useStore } from '../state/atom';
import MyModal from './MyModal';
const width=Dimensions.get('screen').width;
const padding=20
Icon.loadFont()
const MyRow = ({data,ind}) => {
const setModalVisible = useStore(state => state.setPopupState)
const setLoading = useStore(state => state.setWordState)
const selectedData = useStore(state => state.selectedWordState)
const setSelectedData =useStore(state => state.setSelectedWordState)
const deleter = ()=>{
Realm.open({schema:[WordShema]}).then(realm=>{
realm.write(() => {
let obj = realm.objects('Words').filtered("id='"+data.id+"'");
realm.delete(obj)
setLoading(true)
})
})
}
useEffect(() => {
if(selectedData.name!=undefined){
setModalVisible(true)
}
}, [selectedData])
return (
<TouchableOpacity key={ind} style={styles.container} onPress={()=>setSelectedData(data)} >
<MyModal/>
<View style={styles.info} >
<View style={styles.data}>
<Text style={styles.text}>
{data.name}({data.pronunciation})
</Text>
<Text style={styles.text}>
{data.translate}
</Text>
</View>
<Text style={styles.description}>
{data.description}
</Text>
</View>
<TouchableOpacity onPress={()=>deleter()} style={styles.icon}>
<Icon name="delete" size={30} color="red" />
</TouchableOpacity>
</TouchableOpacity>
)
}
export default MyRow
const styles = StyleSheet.create({
container:{
padding:padding/2,
width:width-padding,
alignSelf:'center',
margin:4,
borderRadius:5,
backgroundColor:'#ffffff60',
flexDirection:'row',
shadowColor:'black',
shadowOpacity:0.2,
shadowRadius:1,
shadowOffset:{width: -1, height: 3},
},
info:{
flex:1,
justifyContent:'space-between'
},
data:{
flexDirection:'row',
justifyContent:'space-between'
},
text:{
textAlign:'center',
padding:2,
color:'white',
fontSize:20,
fontWeight:'900',
textShadowColor:'black',
textShadowRadius:5,
textShadowOffset:{width: 0, height: 0},
},
icon:{
alignItems:'center',
justifyContent:'center'
},
description:{
color:'white',
fontSize:14,
fontWeight:'900',
textShadowColor:'black',
textShadowRadius:5,
textShadowOffset:{width: 0, height: 0},
}
})
yes, we can use
npx react-native run-ios
or
npx react-native run-android
Tada it’s working now. Congratulations 🙂
Forgive me if I made any mistakes as this is my first blog post 🙂
I will continue to add more such application development articles on mobile application development with React native, stay tuned 🙂 Stay healthy..