How to use hooks as image's source in react native? - react-native

Im making this menu that when the user clicks at an option, it changes the background image, but i cant use the hook that i created as a parameter to the source of the image. Can someone find where im wrong and how to fix it?
Heres the part of my code referents to the menu and the hooks:
export function Home(){
let imagens = {
vovo: '../assets/vovoJuju.png',
mc: '../assets/mcJuju.png',
pato: '../assets/patoJuju.png',
}
const navigation = useNavigation<any>();
const [showBottomSheet, setShowBottomSheet] = React.useState(false);
const [param, setParam] = useState(1);
const [skin, setSkin] = useState('vovo')
const hide = () => {
setShowBottomSheet(false)
}
function handleAbout(){
navigation.navigate('About');
}
useEffect(() => {
if(param==1){
setSkin('vovo');
}
else if(param==2){
setSkin('mc');
}
else if(param==3){
setSkin('pato');
}
})
return(
<SafeAreaView style={styles.container}>
<TouchableOpacity onPress={handleAbout}>
<Counter />
</TouchableOpacity>
<TouchableOpacity onPress={() => {
setShowBottomSheet(true)
}}
>
<Image source={skin} style={styles.imgvj}/>
</TouchableOpacity>
<BottomSheet show={showBottomSheet} height={290} onOuterClick={hide}>
<Pressable onPress={hide} style={styles.bottomSheetContent}>
<Image source={barrinhaLoja} style={styles.barra}/>
</Pressable>
<View style={styles.conteudoLoja}>
<View style={styles.marginLeft48}>
<TouchableOpacity onPress={() => {
setParam(1);
}}>
<Image source={vovoJuju} style={styles.vovo}/>
<Text style={styles.legendasLoja}>Vovó Juju</Text>
</TouchableOpacity>
</View>
<View>
<TouchableOpacity onPress={() => {
setParam(2);
}}>
<Image source={mcJuju} style={styles.mc}/>
<Text style={styles.legendasLoja}>MC Juju</Text>
</TouchableOpacity>
</View>
<View>
<TouchableOpacity onPress={() => {
setParam(3);
}}>
<Image source={patoJuju} style={styles.pato}/>
<Text style={styles.legendasLoja}>Pato Juju</Text>
</TouchableOpacity>
</View>
</View>
</BottomSheet>
I created the "let imagens", "const param", "const skin" and the "useEffect trying" to make this function. I already tried using the source in different ways such as source={skin} and source={imagens[skin]} but it havent worked.

I'm not certain if this solves your problem, but here's how the first few lines of your component should look like without useEffect:
const imagens = {
vovo: '../assets/vovoJuju.png',
mc: '../assets/mcJuju.png',
pato: '../assets/patoJuju.png',
};
export function Home(){
const navigation = useNavigation<any>();
const [showBottomSheet, setShowBottomSheet] = React.useState(false);
const [param, setParam] = useState(1);
const hide = () => {
setShowBottomSheet(false)
}
function handleAbout(){
navigation.navigate('About');
}
let skin = 'vovo';
switch(param) {
case 1: skin = 'vovo'; break;
case 2: skin = 'mc'; break;
case 3: skin = 'pato'; break;
}
return /* the rest goes here */
}
To reference the actual image, you would use something like {imagens[skin]}.
I moved imagens outside of this function because it never changes, but it doesn't impact anything otherwise.

Related

React native, using TouchableOpacity onPress

I just started learning react native. I am currently trying to implement TouchableOpacity on image rendering from an array and use the info for that element from the array to create a new page. The goal of the code is to have a userInfo page that lists all the images and once you tap on an image, it will show details of that user (you will see just this user and no other ones) using userDetails. I know my TouchableOpacity part will not work, but I don't know how to make it work.
This is from my userInfo.js:
const UserInfo =() => {
const users = [
{userName: "A",
imageSource: require("../../assets/users/A.jpg"),
bio: "this is A"
},
{userName: "B",
imageSource: require("../../assets/users/B.jpg"),
bio: "this is B"
},
{userName: "C",
imageSource: require("../../assets/users/C.jpg"),
bio: "this is C"
}
]
return(
<FlatList
showsVerticalScrollIndicator={false}
keyExtractor={(users)=> users.userName}
data={users}
renderItem = {({item})=>{
return <View>
<TouchableOpacity onPress={userInfoLink(users.userName, users.imageSource, users.bio)}>
<View style={styles.viewBox}><Image style={styles.image} source={item.imageSource}/></View>
</TouchableOpacity>
<Text style={styles.text}>{item.userName}</Text>
</View>;
}}
/>
)
};
This is from my userDetails.js:
const UserDetail=({imageSource, userName, bio}) => {
return <View>
<View style={styles.viewBox}><Image style={styles.image} source={imageSource}/></View>
<Text style={styles.text}>User name: {userName}</Text>
<Text style={styles.text}>Bio: {bio}</Text>
</View>;
}
Ok, after doing some research I found a way to make it work. I used navigation.navigate and passing parameters into the page.
Here is my return code in UserInfo.js:
return(
<FlatList
showsVerticalScrollIndicator={false}
keyExtractor={(users)=> users.userName}
data={users}
renderItem = {({item})=>{
return <View>
<TouchableOpacity onPress={()=>{navigation.navigate('UserDetails', {imageSource: item.imageSource, userName: item.userName, bio:item.bio })}}>
<View style={styles.viewBox}><Image style={styles.image} source={item.imageSource}/></View>
</TouchableOpacity>
<Text style={styles.text}>{item.userName}</Text>
</View>;
}}
/>
)
Here is the code in UserDetails.js:
const UserDetail=({navigation}) => {
const imageSource = navigation.getParam('imageSource', 'a no image image');
const userName = navigation.getParam('userName', 'username error');
const bio = navigation.getParam('bio', 'bio error');
return <View>
<Text style={styles.title}>User Detail</Text>
<View style={styles.viewBox}><Image style={styles.image} source={imageSource}/></View>
<Text style={styles.text}>User name: {userName}</Text>
<Text style={styles.text}>Bio: {bio}</Text>
<Button title="User Info" onPress={()=>{navigation.navigate('UserInfo')}}/>
</View>;
}
I am wondering if adding the parenthesis and arrow was what fixed it.
You went from:
onPress={userInfoLink(users.userName, users.imageSource, users.bio)}
To this:
onPress={()=>{navigation.navigate('UserDetails', {imageSource: item.imageSource, userName: item.userName, bio:item.bio })}}

React Native: change component colour using TouchableOpacity onPress()

I'm making a to-do list to display on a page where the user can click on an icon to mark the task as done, in which the background colour of the corresponding task changes. The issue I'm having is I reuse the 'task' component and cannot specify which component's background should change colour. Hence, clicking any of the icons changes only one component's background colour. GIF of what I mean is below:
Only one component is changing
My code is as follows:
export default function GoalItems(props) {
const goals = props.goals;
if (goals == 1) {
return <Goal goal="Goal 1" />;
} else if (goals == 2) {
return (
<View>
<Goal goal="Goal 1" />
<View style={{marginVertical: 15}} />
<Goal goal="Goal 2" />
</View>
);
} else {
return (
<View>
<Goal goal="Goal 1" />
<View style={{marginVertical: 15}} />
<Goal goal="Goal 2" />
<View style={{marginVertical: 15}} />
<Goal goal="Goal 3" />
</View>
);
}
}
function Goal(props) {
const text = props.goal;
const [checkBox, setCheckBox] = useState(false);
const [checkBoxValue, setCheckBoxValue] = useState(
'ios-checkmark-circle-outline',
);
const [iconColour, setIconColour] = useState('#FF1744');
const [goalColour, setGoalColour] = useState('#64B5F6');
onPressCheckBox = () => {
setCheckBox(!checkBox);
if (checkBox) {
setCheckBoxValue('ios-checkmark-circle');
setIconColour('#1ABC9C');
setGoalColour('#1ABC9C');
} else {
setCheckBoxValue('ios-checkmark-circle-outline');
setIconColour('#FF1744');
setGoalColour('#64B5F6');
}
};
return (
<View style={styles.goalContainer}>
<View style={[{backgroundColor: goalColour}, styles.goal]}>
<Text style={styles.text}>{text}</Text>
</View>
<TouchableOpacity onPress={() => this.onPressCheckBox()}>
<Icon
name={checkBoxValue}
size={40}
style={styles.checkbox}
color={iconColour}
/>
</TouchableOpacity>
</View>
);
}
And the I just render <GoalItems goals={num_of_goals} /> in my main app page. I know its poorly coded with the if statements but I'm not sure how to return X amount of <GoalItems /> given num_of_goals, but that's a separate issue...
Any advice would be appreciated. Thanks in advance!
i think the reason is asynchronous.
When you call setCheckBox(!checkBox) you must wait to it working. When it done, you continue handle new state.
onPressCheckBox = () => {
setCheckBox(!checkBox)
};
useEffect(() => {
if (checkBox) {
setCheckBoxValue('ios-checkmark-circle');
setIconColour('#1ABC9C');
setGoalColour('#1ABC9C');
} else {
setCheckBoxValue('ios-checkmark-circle-outline');
setIconColour('#FF1744');
setGoalColour('#64B5F6');
}
}, [])

How to use React Native Switch inside a functional component?

I am trying to use the Switch component provided by react-native, but it doesn't toggle.
function settings(props) {
let {changeView, header} = props;
let rememberPin = false;
let toggleRememberPin = (value) => {
rememberPin = value;
};
return (
<View style={styles.appContainer}>
<View style={styles.appBody}>
<View style={{flex:1, flexDirection: 'row',justifyContent:'center',alignItems:'center',width: Dimensions.get('screen').width,backgroundColor: Colors.white}}>
<Text>Remember PIN:</Text>
<Switch
onValueChange={toggleRememberPin}
value={rememberPin}
ios_backgroundColor="#aeaeae"
trackColor={{true: Colors.customerGreen, false: '#aeaeae',}}/>
</View>
</View>
</View>
);
}
I get the Switch rendered in the View, I can touch it and it moves from OFF to ON, but suddently it come back to OFF without keeping on ON state.
What's wrong?
You need to look into the core concepts of React, particularly how component state works.
In short, normal variable assignment doesn't cause a component to re-render and reflect changes. That's when you want to use the concept of state.
Here's how to do it properly:
function Settings(props) {
let {changeView, header} = props;
const [rememberPin, setRememberPin] = useState(false);
const toggleRememberPin = (value) => {
setRememberPin(value);
};
return (
<View style={styles.appContainer}>
<View style={styles.appBody}>
<View style={{flex:1, flexDirection: 'row',justifyContent:'center',alignItems:'center',width: Dimensions.get('screen').width,backgroundColor: Colors.white}}>
<Text>Remember PIN:</Text>
<Switch
onValueChange={toggleRememberPin}
value={rememberPin}
ios_backgroundColor="#aeaeae"
trackColor={{true: Colors.customerGreen, false: '#aeaeae',}}/>
</View>
</View>
</View>
);
}

Active is not updating. After a hot reload it is active react native

My child component is below
export default function PickerList ({headingText,listData,hideView,finalpickedItem,onItemSelected,selected} ) {
const {modalHolder,modalHeader,modalHeaderText,modalBody,PerListView,PerListVie wText,okCancel,okCancelHolder,PerListViewActive,
} = styles;
return(
<View style={modalHolder}>
<View style={modalHeader}>
<Text style={modalHeaderText}>{headingText}</Text>
</View>
<View style={modalBody}>
<FlatList data={listData} renderItem={({item , index}) =>
<TouchableOpacity
onPress={() => {
{headingText === 'name'?
onItemSelected(item.name)
: headingText === 'Time' ?
onItemSelected(item.time)
: headingText === 'Property'
onItemSelected(item.property)
}
}}
style={{width:'100%',}}
>
<View
style={
selected===item.name ? PerListViewActive : PerListView > // here i am not getting active hot reload making it active
<Text style={PerListViewText}>
{item.name }
</Text></View>
</TouchableOpacity>
}
keyExtractor={(item, index) => index.toString()}
/>
</View>
</View>
);
};
PickerList.propTypes = {
onItemSelected: PropTypes.func.isRequired,
};
and my parent is
onMenuItemSelected = item => {
console.log(item); // i am getting here selected item
this.setState({ commonSelected: item }); // i am getting final state also.
}
<PickerList
headingText="Property"
listData = {this.state.property_type_options}
hideView = {()=>{this.hideView()}}
finalpickedItem = {()=>{this.finalpickedItem()}}
onItemSelected={this.onMenuItemSelected}
selected = {this.state.commonSelected} /// i have final value here also
/>
issue is "selected" not working every thing is working fine .. selected working but after a hot reload. can i re-render module. state is updating fine but it is not getting active.
I found my answer this is very nice.
extraData={this.state}

React-Native ViewPager goToPage Not Working

import ViewPager from 'react-native-viewpager';
constructor(props){
super(props);
this._renderPage = this._renderPage.bind(this);
this._renderRowSablon = this._renderRowSablon.bind(this);
this.PageChange = this.PageChange.bind(this);
this.count = 0;
this.state = {
count: 0,
info : this.props.values,
page: 0,
pages:pages,
}
}
PageChange(x){
switch(x){
case 'next':
if( this.state.count< (this.state.info.sayfa - 1) ){
this.viewpager.goToPage(this.state.count + 1);
this.setState({count: this.state.count+ 1});
}
break;
}
}
render(){
<View style={{flex:1}}>
<ViewPager
ref={(viewpager) => {this.viewpager = viewpager}}
dataSource={this.state.dataSource}
renderPage={this._renderPage}
onChangePage={this._pageChange}
isLoop={false}
renderPageIndicator={false}
locked={true}
autoPlay={false}/>
</View>
<View style={{flex:1}}>
<TouchableHighlight onPress={() => { this.PageChange('next'); }}>
<Text>Next</Text>
</TouchableHighlight>
</View>
}
When the setState function is cleared, page change is taking place. When the setState function is added (as above) setState works but the page change (gotoPage) does not work. Does not show error / warning What exactly is the problem?
It seems that you are out of scope. When using arrow functions, the scope of 'this' becomes lexical.
Try changing <TouchableHighlight onPress={() => { this.PageChange('next'); }}>
to <TouchableHighlight onPress={this.PageChange('next')}>
See this question:
React-Native: Cannot access state values or any methods declared from renderRow