How work with one array and two react native pickers - react-native

I want to use one data array for two of pickers. If one picker selected one option then I need to remove that option from other picker. I tried this from following code. I used array of length 2.
constructor(props) {
super(props);
this.state = {
startTown: 'Start Point',
endTown: 'End Point',
townList: null,
};
}
componentDidMount(){
firebase.database().ref('busRoutes').once("value",(snapshot)=>{
this.setState({townList:snapshot.val()})
})
}
<Box dir="row">
<Picker
style={{flex: 1}}
selectedValue={startTown}
onValueChange={(value) => {
this.setState({
startTown: value,
});
}}>
<Picker.Item value='Start Point' label='Start Point' />
{townList && townList.map((element,index)=>{
if(element===endTown) return;
return(<Picker.Item value={element} label={element} />)
})}
</Picker>
<Picker
style={{flex: 1}}
selectedValue={endTown}
onValueChange={(value) => {
this.setState({
endTown: value,
});
}}>
<Picker.Item value='End Point' label='End Point' />
{townList && townList.map((element,index)=>{
if(element===startTown) return;
return(<Picker.Item value={element} label={element} />)
})}
</Picker>
</Box>
But it gives error like this
length=2;index=2
here is the link to image with error.
https://imgur.com/ak3tvTB
I can`t put it here as my reputations are not enough

Related

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');
}
}, [])

Card counting functionality react native

I am trying to make an e-commerce app and everything working only the cart icon counts not updating when the user adds an item to cart.
Here is my main page where i am calling component:
<Header headerTitle={this.state.wineD.name} lefticonType={'back'} navigation={this.props.navigation} />
Here is component code:
componentDidMount(){
//API code here and updating response count in state.
if(response.data.success){
this.setState({
cartItems: (response.data.data.cart.items != '' && (response.data.data.cart.items).length > 0)?
(response.data.data.cart.items).length : 0
})
this.props.changeLoaderStatus();
}
}
<FlatHeader
leftIcon={<Icon name={leftIcon} size={20} color="#FFF" />}
leftIconHandler={() => {
(this.props.lefticonType == 'bars' ?
this.props.navigation.dispatch(DrawerActions.openDrawer())
: goBack())
}}
centerContent={
<View style={{width: width*0.7,alignItems:'center'}}>
<Text numberOfLines={1} style={{ color: '#FFF',fontSize:22,fontWeight:'bold' }}>{this.props.headerTitle}</Text>
</View>
}
rightIcon={<Group><Icon name="shopping-cart" size={20} color="#FFF" />
<View style={{width:16,height:16,borderRadius:8,backgroundColor:'red',justifyContent:'center',
alignItems:'center',marginBottom:14}}>
<Text style={{fontSize:10,color:'#fff',fontWeight:'bold'}}>{this.state.cartItems}</Text></View></Group>}
rightIconHandler={() => this.props.navigation.navigate('Cart')}
large
style={{ backgroundColor: '#d7b655' }}
/>
This is the screen where from other component updating the cart
Anyone have solution please share here.
If I understood correctly your problem, you may need to modify this.setState in this way:
componentDidMount(){
//API code here and updating response count in state.
if(response.data.success){
this.setState({
cartItems: (response.data.data.cart.items != '' && (response.data.data.cart.items).length > 0)?
(response.data.data.cart.items).length : 0
},()=>{
this.props.changeLoaderStatus(); }) } }
try this and let me know if it works for you.

React Native - Change other icons color on click

I've been searching for a few days to solve this problem. I need to change another icon's color when i click in one of them.
I'm using react-native-vector-icons
this.setState({
listaPlantel: Object.entries(dataArray).map(function ([key, nome]) {
if (that.state.mercado.status_mercado == 2) {
dadosAtleta = that.state.pontuados[nome.atleta_id];
}
return (
<ListItem avatar key={key} button onPress={() => that.detailsScreen(nome)}>
<Left>
<Thumbnail source={{ uri: nome.foto.replace('FORMATO', '80x80') }} />
</Left>
<Body>
<Text>{nome.apelido}</Text>
<Text note>{that.state.posicoes ? that.state.posicoes[nome.posicao_id]['nome'] : ''} - {that.state.clubes ? that.state.clubes[nome.clube_id]['nome'] : ''}</Text>
<Text style={{ textAlign: 'left' }}>Última: {nome.pontos_num} Média: {nome.media_num} {' $' + nome.preco_num}</Text>
</Body>
<Right>
{/*<Text>{dadosAtleta ? dadosAtleta['pontuacao'] : nome.pontos_num}</Text>*/}
<Icon name="md-close-circle" size={30} />
<Icon type="Foundation" name="md-contact" key={key} size={30} color={that.state.id_capitao === nome.atleta_id ? that.state.corCap : that.state.corGeral} onPress={() => that.setState({ id_capitao: nome.atleta_id })} />
</Right>
</ListItem>
)
}),
});
It seems you are putting conditions and functions within setState I would recommend you read about the lifecycle and app state here:
https://reactjs.org/docs/state-and-lifecycle.html
As an example of how to update values, of which you're trying to do - take this scenario into consideration:
initial colour : red, updated colour : blue (For example)
in your constructor:
constructor (props) {
super(props);
this.state = {
/*Initial State and Colour*/
iconColour : "red"
}
}
in your render method:
<ListItem avatar key={key} button onPress={() => that.detailsScreen(nome)}>
<Icon color={this.state.iconColour}/>
</ListItem>
Within your onPress function:
this.setState({
iconColor : "blue"
})

Custom Send button and clear textInput react-native-gifted-chat

I'm using react-native-gifted-chat and have a custom Send button, but how can I properly call onSend using my own Send button and after that how can I clear the inpuxText element?
Thanks.
You can define the renderSend function:
renderSend = (sendProps) => {
<TouchableOpacity>
<Image source={require('path/to/your/button/icon')} />
</TouchableOpacity>
);
}
<GiftedChat renderSend={this.renderSend} />
More info here: https://github.com/FaridSafi/react-native-gifted-chat/issues/480
As for clearing the text input, perhaps you could use redux and clear the textInput by returning a blank textInput?
For example:
case MESSAGE_SENT:
return { ...state, error: action.payload, loading: false, textInput: '' };
So it took me a while but I finally got it
<GiftedChat
messages={messages}
textInputStyle={styles.textInput}
onSend={messages => onSend(messages)}
multiline
user={{
_id: 1,
}}
renderSend={(props)=>{
const {text,messageIdGenerator,user, onSend} = props
return(
<TouchableOpacity onPress= {
()=>{
if (text && onSend) {
onSend({ text: text.trim(), user:user,_id:messageIdGenerator()}, true);
}
}
} style={styles.sendButton}>
<Send/>
</TouchableOpacity>
)}}
/>
as for using redux to clear it is a bit redundant, and you will have to work with a large object in redux which is not too go for performance
Just go to the main implementation of send.js in react native gifted chat
https://www.github.com/FaridSafi/react-native-gifted-chat/tree/master/src%2FSend.tsx
Better solution
import { GiftedChat, Send } from 'react-native-gifted-chat'
<Send {...props} >
<View style={{justifyContent: 'center', height: '100%', marginRight: 10}}>
<Icon
name='send'
type='ionicon'
size={24}
color={Colors.primaryColor}
/>
</View>
</Send>

Conditional Rendering on Items of Native Base Picker [React Native]

I’m using ‘Native Base’ components for our product and going good with this,
but I’m stuck at one point and it is around putting Items in Nativebase Picker. My code is like this
Render Method code -
render(){
return (
<View style={{marginTop: 20, flexDirection:'row', flexWrap:'wrap', justifyContent:'space-around', alignItems:'center'}}>
<View style={{flex:1, justifyContent:'center', alignItems:'flex-end' }}>
<Button
style={{ backgroundColor: '#6FAF98', }}
onPress={this._showDateTimePicker}
>
<Text>Select Date</Text>
</Button>
</View>
<View style={{flex:1, justifyContent:'center', alignItems:'stretch'}}>
<Picker
style={{borderWidth: 1, borderColor: '#2ac', alignSelf:'stretch'}}
supportedOrientations={['portrait','landscape']}
iosHeader="Select one"
mode="dropdown"
selectedValue={this.state.leaveType}
onValueChange={(value)=>this.setState({leaveType:value,})
//this.onValueChange.bind(this)
}>
<Item label="Full Day" value="leave1" />
{
this.showStartDateFirstHalf() // Here I want to show this picker item on the basis of a condition
}
<Item label="2nd half" value="leave3" />
</Picker>
</View>
<DateTimePicker
isVisible={this.state.isStartDatePickerPickerVisible}
onConfirm={this._handleDatePicked}
onCancel={this._hideDateTimePicker}
mode='date'
/>
</View>
);
}
showStartDateFirstHalf()
{
if(!this.state.isMultipleDays)
{
return(
<Item label="1st Half" value="leave2" />
);
}
}
So, this code is working fine if this.state.isMultipleDays is false, But when this.state.isMultipleDays is true, it means when it is in else part then i'm getting this error -
Cannot read property 'props' of undefined
I think there's an easier answer to this. Instead of creating the separate showStartDateFirstHalf() function try this:
render() {
const pickerItems = [
{
label: 'Full Day',
value: 'leave1',
},
{
label: '1st Half',
value: 'leave2',
},
{
label: '2nd Half',
value: 'leave3',
},
];
const filteredItems = pickerItems.filter(item => {
if (item.value === 'leave2' && this.state.isMultipleDays) {
return false;
}
return true;
});
// The 'return' statement of your render function
return (
...
<Picker ...>
{(() =>
filteredItems.map(item =>
<Item label={item.label} value={item.value} />
)()}
</Picker>
...
);
}
That way, you already have a list of items that is determined before the return statement of the render cycle. Also the use of filter instead of map will not just give you null as the second item if the condition is not met, but will remove the item altogether.