props.onClick undefined checkbox React Native - react-native

I am using the Checkbox component for my code and I have a list of elements and for each element I have a checkbox. However, my checkbox returns the following error when I check it on the phone simulator :
TypeError: this.props.onClick is not a function. (In 'this.props.onClick()', 'this.props.onClick' is undefined)
I don't understand because a checkbox does not require the onClick function ...
Please see my code below if needed:
import CheckBox from 'react-native-check-box'
export default class List extends Component {
constructor(props) {
super(props)
this.state = {
names: [
{
key: 0,
name: 'Element1',
isChecked: false
},
{
key: 1,
name: 'Element2',
isChecked: false,
}
]
}
}
checkboxTest(key){
let names = this.state.names.reduce((acc,name)=>{
if(name.key === key){
return {...name, isChecked: !name.isChecked}
}
return name
}, [])
this.setState({names})
console.table(names)
}
render(){
return (
<ScrollView>
<View>
{
this.state.names.map((item) => (
<View style={styles.background}>
<Text style = {styles.title}>{item.name}</Text>
<CheckBox value={false} onChange={()=>this.checkboxTest(item.key)}/>
</View>
))
}
</View>
</ScrollView>
)
}
}

If you read the documentation carefully, you will noticed that this checkbox component requires a onClick function, which you did not provide. Hence, instead of writing onChange, you should be using onClick instead
<CheckBox
style={{flex: 1, padding: 10}}
onClick={()=>{
this.setState({
isChecked:!this.state.isChecked
})
}}
isChecked={this.state.isChecked}
leftText={"CheckBox"}
/>

According to react-native-check-box documentation prop onClick is isRequired. But you are passing onChange not onClick.
Change your onChange to onClick in order to fix the error. Also change value to isChecked.
<CheckBox isChecked={false} onClick={()=>this.checkboxTest(item.key)}/>
Edit
Check below complete example for information
import * as React from "react";
import { Text, View } from "react-native";
import CheckBox from "react-native-check-box";
export default class List extends React.Component {
constructor(props) {
super(props);
this.state = {
names: [
{
key: 0,
name: "Element1",
isChecked: false
},
{
key: 1,
name: "Element2",
isChecked: false
}
]
};
}
checkboxTest = key => {
let names = this.state.names.reduce((acc, name) => {
if (name.key === key) {
acc.push({ ...name, isChecked: !name.isChecked });
} else {
acc.push(name);
}
return acc;
}, []);
this.setState({ names });
};
render() {
return (
<View>
{this.state.names.map((item, index) => (
<View style={{ flexDirection: " row" }}>
<Text>{item.name}</Text>
<CheckBox
isChecked={
this.state.names.find(item => item.key == index).isChecked
}
onClick={() => this.checkboxTest(item.key)}
/>
</View>
))}
</View>
);
}
}
Hope this helps you. Feel free for doubts.

Related

How to multiselect items in flatlist react native

How to multi select and highlight the components in a react native flatlist. I have checked the doc. But it is bit confusing can anybody help me. I have done single select using this method.Could any one modify this to a multi select.I will give the snack link here where i have done the single select
import * as React from 'react';
import {
Text,
View,
StyleSheet,
FlatList,
TouchableOpacity,
} from 'react-native';
import Constants from 'expo-constants';
const Data = [
{
id: 1,
first_name: 'Sile',
},
{
id: 2,
first_name: 'Clementia',
},
{
id: 3,
first_name: 'Brita',
},
{
id: 4,
first_name: 'Duke',
},
{
id: 5,
first_name: 'Hedvig',
},
{
id: 6,
first_name: 'Paulie',
},
{
id: 7,
first_name: 'Munmro',
},
{
id: 8,
first_name: 'Dyanna',
},
{
id: 9,
first_name: 'Shanta',
},
{
id: 10,
first_name: 'Bambi',
},
];
// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedItem: null,
};
}
onPressHandler(id) {
this.setState({ selectedItem: id });
}
render() {
return (
<View>
<FlatList
extraData={this.state.selectedItem} //Must implemented
//horizontal={true}
data={Data}
keyExtractor={item => item.id.toString()}
showsHorizontalScrollIndicator={false}
renderItem={({ item }) => (
<TouchableOpacity onPress={() => this.onPressHandler(item.id)}>
<Card
style={
this.state.selectedItem === item.id
? {
padding: 10,
borderRadius: 5,
backgroundColor: '#000000',
}
: {
padding: 10,
borderRadius: 5,
backgroundColor: '#a1a1a1',
}
}>
<Text>{item.first_name}</Text>
</Card>
</TouchableOpacity>
)}
/>
</View>
);
}
}
const styles = StyleSheet.create({
});
this is the sample data
I have made some changes and made your flatlist as multiselect. Please visit this link.
I have made below changes for making this as multiselect:
Added dummy data in state & passed it to flatlist's data.
On item press iterate data and for corresponding item set item.selected=true.
Inside flatlist's renderItem if item.selected==true then show selection else remove selection.
Please check and let me know.
check this logic,
...
this.state = {
clientsArray: clientsArray,
selectedClients: []
};
//'clientsArray' is your data array
...
_renderCell = ({ item, index }) => {
const { selectedClients, clientsArray } = this.state;
let isSelected =
selectedClients.filter(o => {
return o.id === item.id;
}).length > 0
? true
: false;
//change your UI based on the 'isSelected' value
return (
<TouchableOpacity
activeOpacity={Constants.ACTIVE_OPACITY}
onPress={() => {
this._didSelectClient(item);
}}
>
{
//Your component
}
</TouchableOpacity>
}
_didSelectClient = selectedItem => {
let selectedClients = this.state.selectedClients;
let isItemSelected =
selectedClients.filter(item => {
return item.id.includes(selectedItem.id);
}).length > 0
? true
: false;
if (isItemSelected) {
const index = selectedClients.findIndex(
obj => obj.id === selectedItem.id
);
selectedClients.splice(index, 1);
} else {
selectedClients.push(selectedItem);
}
this.setState({ selectedClients });
};
render() {
...
<FlatList
style={{ flex: 1 }}
data={clientsArray}
renderItem={this._renderCell}
keyExtractor={(item, index) => index.toString()}
extraData={this.props}
ListEmptyComponent={this._renderEmptyComponent}
/>
...
}

React Native - Ref seems to be undefined

can somebody please help me with "ref" in this code. In the last "view" component, it seems that "this.multiSelect" is undefined. I dont understand why and where do I make mistake. Thas it have something with context or?
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import MultiSelect from 'react-native-multiple-select';
export default class MultiSelectComponent extends Component {
constructor() {
super();
this.state = {
selectedItems : []
};
this.items = [{
id: '92iijs7yta',
name: 'Ondo',
}, {
id: 'suudydjsjd',
name: 'Abuja',
}];
}
onSelectedItemsChange = selectedItems => {
this.setState({ selectedItems });
};
render() {
const { selectedItems } = this.state;
return (
<View style={{ flex: 1 }}>
<MultiSelect
hideTags
items={this.items}
uniqueKey="id"
ref={(component) => { this.multiSelect = component; }}
onSelectedItemsChange = {this.onSelectedItemsChange}
selectedItems={selectedItems}
selectText="Pick Items"
searchInputPlaceholderText="Search Items..."
submitButtonText="Submit"
/>
<View>
{this.multiselect
?
this.multiselect.getSelectedItemsExt(selectedItems)
:
null}
</View>
</View>
);
}
}
You have a typo in your code, the error is maybe there :
you are using this.multiselect and declaring
ref={(component) => { this.multiSelect = component; }}
so maybe with thi :
ref={(component) => { this.multiselect = component; }}

React Native Checkbox not working

I have my react-native app consisting of a form. I have implemented two check-boxes with their state set to boolean true. I want boolean true or false to get submitted to the database from those check-boxes but the check-box button won't work.
Here's my code:
import React, { Component } from 'react';
import { View, Text, Button, TextInput, StyleSheet } from 'react-native';
import { CheckBox } from 'react-native-elements';
import axios from 'axios';
export default class Delivery extends Component {
constructor(props) {
super(props);
this.state = {
trackingNo: '',
weight: '',
length: '',
width: '',
//checked: true,
delivered: { checked: true }
};
}
componentDidMount(){
fetch('https://courierapp-test.herokuapp.com/products/')
.then(
function(response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ' +
response.status);
return;
}
// Examine the text in the response
response.json().then(function(data) {
console.log(data);
});
}
)
.catch(function(err) {
console.log('Fetch Error :-S', err);
});
}
onPressSubmit(){
axios.post('https://courierapp-test.herokuapp.com/products/', {
requestId: this.state.trackingNo,
parcelWeight: this.state.weight,
parcelLength: this.state.length,
parcelWidth: this.state.width,
parcelPickup: this.state.pickup,
parcelDelivered: this.state.delivered,
})
.then(function (response) {
console.log(response, "data sent");
})
.catch(function (error) {
console.log(error, "data not sent");
});
}
render() {
return (
<View style={{padding: 15}}>
<TextInput
style={styles.inputStyle}
placeholder="Request Id"
onChangeText={(trackingNo) => this.setState({trackingNo})}
value={this.state.trackingNo}
/>
<CheckBox style={styles.checkStyle}
title='Pickup'
checked={this.state.checked}
/>
<CheckBox style={styles.checkStyle}
title='Delivered'
onValueChange={() => this.setState({ checked: !this.state.checked })}
/>
<TextInput
style={styles.inputStyle}
placeholder="Enter Parcel Weight(Kg)"
onChangeText={(weight) => this.setState({weight})}
value={this.state.weight}
/>
<TextInput
style={styles.inputStyle}
placeholder="Enter Parcel Length(Cm)"
onChangeText={(length) => this.setState({length})}
value={this.state.length}
/>
<TextInput
style={styles.inputStyle}
placeholder="Enter Parcel Width(Cm)"
onChangeText={(width) => this.setState({width})}
value={this.state.width}
/>
<Button
onPress={() => {
this.onPressSubmit()
}
}
title="Submit"
color="#1ABC9C"
/>
</View>
);
}
}
const styles = StyleSheet.create({
inputStyle: {
color: '#1ABC9C',
height: 40,
borderWidth: 0
}
});
I have tried every work around but could not solve it. the checkbox keeps on blinking only upon clicking but could not change the state checked or unchecked and also no value getting submitted to database.
Define variable checked in state
this.state = {
checked: false
};
create a method
onChangeCheck() {
this.setState({ checked: !this.state.checked})
}
And use onChange() prop of Chekbox to update the state and provide value to the check box like this
<CheckBox
style={styles.checkBox}
value={this.state.checked}
onChange={() => this.onChangeCheck()} />
Try changing value inside event onValueChange
<CheckBox value={this.aBooleanField} onValueChange={() => {
this.aBooleanField = !this.aBooleanField;
this.updateView();
}}/>
The updateView is like this:
updateView() {
this.setState({ viewChanged: !this.state.viewChanged})
}
Also works for < Switch /> component, and you can use updateView to only to refresh the view, setState it's to keep state values (when you resume app, rotate screen, etc).

Hot to get selected value from another component?

I create a component Confirm.js with react-native <Modal /> that has two DropDownMenu and two <Button />.
I want user click the Yes <Button /> than i can get the DropDownMenu onOptionSelected value. I think i should use this.props but i have no idea how to do it.
I want get the value in MainActivity.js from Confirm.js
Any suggestion would be appreciated. Thanks in advance.
Here is my MainActivty.js click the <Button /> show <Confirm />:
import React, { Component } from 'react';
import { Confirm } from './common';
import { Button } from 'react-native-elements';
class MainActivity extends Component {
constructor(props) {
super(props);
this.state = { movies: [], content: 0, showModal: false, isReady: false };
}
// close the Confirm
onDecline() {
this.setState({ showModal: false });
}
render() {
return (
<View style={{ flex: 1 }}>
<Button
onPress={() => this.setState({ showModal: !this.state.showModal })}
backgroundColor={'#81A3A7'}
containerViewStyle={{ width: '100%', marginLeft: 0 }}
icon={{ name: 'search', type: 'font-awesome' }}
title='Open the confirm'
/>
<Confirm
visible={this.state.showModal}
onDecline={this.onDecline.bind(this)}
>
</Confirm>
</View>
);
}
}
export default MainActivity;
Confirm.js:
import React from 'react';
import { Text, View, Modal } from 'react-native';
import { DropDownMenu } from '#shoutem/ui';
import TestConfirm from './TestConfirm';
import { CardSection } from './CardSection';
import { Button } from './Button';
import { ConfirmButton } from './ConfirmButton';
const Confirm = ({ children, visible, onAccept, onDecline }) => {
const { containerStyle, textStyle, cardSectionStyle } = styles;
return (
<Modal
visible={visible}
transparent
animationType="slide"
onRequestClose={() => {}}
>
<View style={containerStyle}>
<CardSection style={cardSectionStyle}>
{/* Here is my DropDownMenu */}
<TestConfirm />
</CardSection>
<CardSection>
<ConfirmButton onPress={onAccept}>Yes</ConfirmButton>
<ConfirmButton onPress={onDecline}>No</ConfirmButton>
</CardSection>
</View>
</Modal>
);
};
const styles = {
cardSectionStyle: {
justifyContent: 'center'
},
textStyle: {
flex: 1,
fontSize: 18,
textAlign: 'center',
lineHeight: 40
},
containerStyle: {
backgroundColor: 'rgba(0, 0, 0, 0.75)',
position: 'relative',
flex: 1,
justifyContent: 'center'
},
buttonStyle: {
flex: 1,
alignSelf: 'stretch',
backgroundColor: '#fff',
borderRadius: 5,
borderWidth: 1,
borderColor: '#007aff',
marginLeft: 5,
marginRight: 5
}
};
export { Confirm };
TestConfirm.js
import React, { Component } from 'react';
import { View } from 'react-native';
import { DropDownMenu, Title, Image, Text, Screen, NavigationBar } from '#shoutem/ui';
import {
northCities,
centralCities,
southCities,
eastCities,
islandCities
} from './CityArray';
class TestConfirm extends Component {
constructor(props) {
super(props);
this.state = {
zone: [
{
id: 0,
brand: "North",
children: northCities
},
{
id: 1,
brand: "Central",
children: centralCities
},
{
id: 2,
brand: "South",
children: southCities
},
{
id: 3,
brand: "East",
children: eastCities
},
{
id: 4,
brand: "Island",
children: islandCities
},
],
}
}
render() {
const { zone, selectedZone, selectedCity } = this.state
return (
<Screen>
<DropDownMenu
style={{
selectedOption: {
marginBottom: -5
}
}}
styleName="horizontal"
options={zone}
selectedOption={selectedZone || zone[0]}
onOptionSelected={(zone) =>
this.setState({ selectedZone: zone, selectedCity: zone.children[0] })}
titleProperty="brand"
valueProperty="cars.model"
/>
<DropDownMenu
style={{
selectedOption: {
marginBottom: -5
}
}}
styleName="horizontal"
options={selectedZone ? selectedZone.children : zone[0].children} // check if zone selected or set the defaul zone children
selectedOption={selectedCity || zone[0].children[0]} // set the selected city or default zone city children
onOptionSelected={(city) => this.setState({ selectedCity: city })} // set the city on change
titleProperty="cnCity"
valueProperty="cars.model"
/>
</Screen>
);
}
}
export default TestConfirm;
If i console.log DropDownMenu onOptionSelected value like the city it would be
{cnCity: "宜蘭", enCity: "Ilan", id: 6}
I want to get the enCity from MainActivity.js
ConfirmButton.js:
import React from 'react';
import { Text, TouchableOpacity } from 'react-native';
const ConfirmButton = ({ onPress, children }) => {
const { buttonStyle, textStyle } = styles;
return (
<TouchableOpacity onPress={onPress} style={buttonStyle}>
<Text style={textStyle}>
{children}
</Text>
</TouchableOpacity>
);
};
const styles = {
{ ... }
};
export { ConfirmButton };
You can pass a function to related component via props and run that function with the required argument you got from the dropdowns. Because you have couple of components in a tree it is going to be a little hard to follow but if you get the idea I'm sure you'll make it simpler. Also after getting comfortable with this sort of behavior and react style coding you can upgrade your project to some sort of global state management like redux, flux or mobx.
Sample (removed unrelated parts)
class MainActivity extends Component {
onChangeValues = (values) => {
// do some stuf with the values
// value going to have 2 properties
// { type: string, value: object }
const { type, value } = values;
if(type === 'zone') {
// do something with the zone object
} else if(type === 'city') {
// do something with the city object
}
}
render() {
return(
<Confirm onChangeValues={this.onChangeValues} />
)
}
}
const Confirm = ({ children, visible, onAccept, onDecline, onChangeValues }) => {
return(
<TestConfirm onChangeValues={onChangeValues} />
)
}
class TestConfirm extends Component {
render() {
return(
<Screen>
<DropDownMenu
onOptionSelected={(zone) => {
// run passed prop with the value
this.props.onChangeValues({type: 'zone', value: zone});
this.setState({ selectedZone: zone, selectedCity: zone.children[0] });
}}
/>
<DropDownMenu
onOptionSelected={(city) => {
// run passed prop with the value
this.props.onChangeValues({type: 'city', value: city});
this.setState({ selectedCity: city })
}}
/>
</Screen>
)
}
}

React Native onPress active state change image source on Carousel

Trying to change image of a button on my carousel elements, currently it (below code) changes all the images when I click any of them. I'd like change that only current carousel's image. Any ideas? Thanks
class CarouselImages extends React.Component {
constructor(props) {
super(props);
this.state = {
myImagesArray: [
{
key: 1,
title: 'Category'
},
{
key: 2,
title: 'Category'
},
{
key: 3,
title: 'Category'
}
],
icon_active: false,
}
activateCarouselButton = a => {
const newState = Object.assign(
{},
{
icon_active: false,
},
{ [a]: true },
)
this.setState(newState);
}
}
render = () => {
const { icon_active } = this.state;
var myCarousel = this.state.myImagesArray.map(function (index) {
return (
<View key={index}>
<TouchableHighlight onPress={() => activateCarouselButton('icon_active')} >
<Image
source={icon_active ? require('../Image/active#2x.png') : require('../Image/disabled#2x.png')} />
</TouchableHighlight>
</View>
);
});
return (
<View>
<Carousel
style={{ backgroundColor: '#fff' }}>
{myCarousel}
</Carousel>
</View>
)
}
}
You need to hold key of the icon in the icon_active state, not a boolean. This gives you a hunch on how to do it:
render() {
const { icon_active } = this.state;
return (
this.state.myImagesArray.map((image) => {
return (
<View key={image.key}>
<TouchableHighlight onPress={() => activateCarouselButton(image.key)}>
<Image source={icon_active === image.key ? require('../Image/active#2x.png') : require('../Image/disabled#2x.png')} />
</TouchableHighlight>
</View>
)
})
)
}
<Image source={this.props.secureTextEntry ?
require('../../assets/images/signup/Showpassword.png') :
require('../../assets/images/signup/Hidepassword.png')} />