I am React Native Beginner and am using expo-radio-button.
But i am unable to select a single radio button at a time in flatlist.
if i select single button it will select only one button.
help me to fix this.
i need to show and select yes or no in the radio button for each questions
Click here to see output that i want
var myArray = [
{
isSignReq: "1",
sno: "1",
yesno: "0",
},
{
isSignReq: "1",
sno: "2",
yesno: "0",
},
{
isSignReq: "1",
sno: "3",
yesno: "0",
},
];
const [account, setAccount] = useState([]);
const setFormSubmit = (val) => {
console.log(val);
};
<FlatList
data={myArray}
keyExtractor={() => {
return (
new Date().getTime().toString() +
Math.floor(Math.random() * Math.floor(new Date().getTime())).toString()
);
}}
renderItem={(itemData) => {
return (
<View style={{ flexDirection: "row", marginVertical: "2%" }}>
<Text style={styles.data1}>{itemData.item.sno}</Text>
<Text style={styles.data2}>{itemData.item.name}</Text>
<View style={{ width: "30%", marginLeft: "1%" }}>
<RadioButtonGroup
onSelected={(value) => {
setFormSubmit(value), setAccount(value);
}}
selected={account}
size={22}
containerStyle={{ flexDirection: "row" }}
>
<RadioButtonItem label={"Yes"} value={itemData.item.isSignReq} />
<RadioButtonItem label={"No"} value={itemData.item.yesno} />
</RadioButtonGroup>
</View>
</View>
);
}}
/>
renderItem = ({item, index}) => {
.....
<RadioButton
innerColor={Colors.darkBlue}
outerColor={Colors.lightGray}
animation={'bounceIn'}enter code here
isSelected={this.state.selectedIndex === index}
onPress={() => {this.onPress(index)}}
/>
}
and replace onPress with
onPress = (index) => {
this.setState({ selectedIndex: index });
}
and update FlatList with extraData props as FlatList needs to be re-rendered as
<FlatList
keyExtractor={this._keyExtractor}
data={this.state.data}
renderItem={this.renderItem}
ItemSeparatorComponent={this.renderSeparator}
extraData={this.state}
/>
demo: https://snack.expo.dev/HkzA9cCSB
Related
How do I make the text "BIRD" label that will check the checkbox while press on it ?
According to my example it does not work and it is not clear to me.
import CheckBox from '#react-native-community/checkbox';
function App(props) {
const isSelected = useSelector((rootState) => rootState.BitzuaDigumReducer.checkBox);
return (
<TouchableOpacity
activeOpacity={1}
style={{
flexDirection: 'row',
alignSelf: 'flex-start',
top: 20,
left: 10,
}}
>
<CheckBox
value={isSelected}
onValueChange={(value) => dispatch(setCheckBox(value))}
style={styles.checkbox}
tintColors={{ true: 'white', false: 'white' }}
/>
<Text style={styles.label}>BIRD</Text>
</TouchableOpacity>
);
}
I mocked Checkbox on this example, but please review it. It should give you a basic idea on how to toggle checkbox value by pressing the label: https://snack.expo.io/#zvona/toggle-checkbox-on-label
Core code:
const App = () => {
const [isSelected, setSelected] = useState(false);
const toggleCheckbox = () => {
setSelected(!isSelected);
// Here you can dispatch the event to state management
};
return (
<View style={styles.container}>
<Checkbox onValueChange={toggleCheckbox} selected={isSelected} />
<TouchableOpacity activeOpacity={0.8} onPress={toggleCheckbox}>
<Text style={styles.label}>{'Label'}</Text>
</TouchableOpacity>
</View>
);
};
I am new to react native and was trying to display some data into a react component (preferably cards) but for now FlatList will work. I was unable to destructure the data and display it. How should it be done?
import React,{useState,useEffect} from 'react';
import { StyleSheet,Modal, View ,Text , ScrollView, Alert} from 'react-native';
import {IconButton ,Appbar, Card, TextInput ,Button ,
} from 'react-native-paper';
import firebase from './config';
import { LogBox } from 'react-native';
LogBox.ignoreLogs(['Setting a timer']);
export default function PlantATree(){
const [modalVisible, setModalVisible] = useState(false);
const [name,setName]=useState('');
const [title, setTitle]=useState('');
const [description, setDescription]=useState('');
const [data, setmyData]=useState([])
const savePost = () =>{
firebase.database()
.ref('posts')
.push({
"id":Math.random(),
"name":name,
"title":title,
"description":description,
})
setTimeout(()=>{
Alert.alert("Your post is saved successfully :D")
},1000)
}
useEffect(()=>{
const data = firebase.database().ref("posts");
data.on("value", datasnap =>{
//console.log(Object.values(datasnap.val()));
if(datasnap.val()){
setmyData(datasnap.val());
}
})
},[]);
//console.log(data);
const src= Object.keys(data);
console.log("Hi",src);
return (
<ScrollView>
<Appbar.Header>
<Appbar.Content title="Plant a tree Initiative"/>
</Appbar.Header>
<IconButton
icon="plus"
color="crimson"
size={30}
onPress={() => setModalVisible(true)}
/>
<View style={styles.centeredView}>
{/*Modal Content Starts Here*/}
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
>
<View style={styles.centeredView}>
<ScrollView style={styles.modalView}>
<Appbar.Header style={{ padding:10}}>
<Appbar.Content title="Share your story.." />
</Appbar.Header>
<Card>
<Card.Content >
<View style={{marginLeft:0,marginRight:0,
}}>
<Card >
<Card.Content>
<TextInput
style={{}}
label="Your name...."
mode="outlined"
value={name}
onChangeText={text =>{ setName(text)}}
/>
<TextInput
style={{}}
label="Story Title...."
mode="outlined"
value={title}
onChangeText={text =>{ setTitle(text)}}
/>
<TextInput
style={styles.formcomponents}
label="Share your thoughts...."
mode="outlined"
multiline={true}
numberOfLines={8}
value={description}
onChangeText={text =>{ setDescription(text)}}
/>
</Card.Content>
</Card>
</View>
<Card>
<Button mode="contained" style={{margin:20}}
onPress={savePost}>
post
</Button>
<Button mode="contained" style={{margin:20,backgroundColor:'crimson'}} onPress={() => setModalVisible(!modalVisible)}>
close
</Button>
</Card>
</Card.Content>
</Card>
</ScrollView>
</View>
</Modal>
</View>
<View>
{/* DATA FROM FIREBASE */}
<Text>{data?.description}</Text>
</View>
</ScrollView>
)
}
const styles = StyleSheet.create({
centeredView: {
marginTop: 45,
marginBottom:45,
},
modalView: {
backgroundColor: "white",
borderRadius: 20,
marginTop:70,
marginBottom:20,
marginRight:20,
marginLeft:20,
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5
},
openButton: {
backgroundColor: "#F194FF",
borderRadius: 20,
padding: 10,
elevation: 2
},
textStyle: {
color: "white",
fontWeight: "bold",
textAlign: "center"
},
});
Data Format:
Object {
"-MQXpKu8Zh1PCVsBLquO": Object {
"description": "Good story.",
"id": 0.8842625745597491,
"name": "Subhodeep",
"title": "Story 1 ",
},
"-MQXpRXS5_6m6YTZ39e0": Object {
"description": "Good story 2.",
"id": 0.8767685757714464,
"name": "Sanjoy",
"title": "Story 2",
},
"-MQXpX7ku-41CreQ8SOP": Object {
"description": "Good story 3.
",
"id": 0.9976208307830834,
"name": "Sanchari",
"title": "Story 3",
},
Since the data from Firebase consists of multiple nodes, you'll need to iterate over the results and map each child to a new component.
I typically find that easiest by first converting the snapshot to an array (instead of an Object) when it is loaded:
useEffect(()=>{
const data = firebase.database().ref("posts");
data.on("value", datasnap =>{
let data = [];
datasnap.forEach((childsnap) => {
let val = childsnap.val();
val["$key"] = childsnap.key;
data.push(val);
})
setmyData(data);
})
},[]);
Then in the rendering code we can loop over this data array and render a component for each item:
data.map((item) => <Text id={item["$key"]}>{item.description}</Text>)
There might be some syntax errors in the rendering, but the overall flow should be clear from this.
I created a checkbox inside my flatlist but when I click on the checkbox all the check boxes will render. I want to render the checkbox I press not the entire checkboxes.
This is my code.
const ScreenCart = () => {
const [checked, setChecked] = useState(false)
const renderItem = ({ item, index }) => {
return (
<View style={styles.list}>
<View style={{ flexDirection: 'row' }}>
<CheckBox
checkBoxColor={COLORS.ORANGE}
isChecked={checked}
onClick={() => setChecked(!checked)}
/>
<Image
source={item.image}/>
<View>
<Text numberOfLines={1} style={[styles.item, { width: 210 * rate }]}>{item.name}
</Text>
</View>
</View>
</View>
)
}
return (
<View style={{ backgroundColor: COLORS.WHITE, flex: 1 }}>
<View style={{ flex: 1 }}>
<Flatlist
data={TEMP_DATA_CART}
renderItem={renderItem}
keyExtractor={(item) => item.id.toString()}>
/>
</View>
)
this is my data.
TEMP_DATA_CART = [
{
id: '1', image: IMAGES.imgPromote, name: 'Sữa tắm Prunus - Premier Herb', value: 180000, quantity: 1, checked: false,
},
{
id: '2', image: IMAGES.imgPromote, name: 'Sữa tắm Prunus - Premier Herb', value: 180000, quantity: 1, checked: false,
},
{
id: '3', image: IMAGES.imgPromote, name: 'Sữa tắm Prunus - Premier Herb', value: 180000, quantity: 1, checked: false,
},
you set a global state so it is selecting checkbox for all items
remove this
const [checked, setChecked] = useState(false)
set array of selected id's
const [checked, setChecked] = useState([]);
on press set id in array and set check status from array
<CheckBox
checkBoxColor={COLORS.ORANGE}
isChecked={checked.includes(item.id)}
onClick={() => {
const newIds = [...checked];
const index = newIds.indexOf(item.id);
if (index > -1) {
newIds.splice(index, 1);
} else {
newIds.push(item.id)
}
setChecked(newIds)
}}
/>
and in flatlist set extraData prop
<Flatlist
data={TEMP_DATA_CART}
renderItem={renderItem}
extraData={checked}
keyExtractor={(item) => item.id.toString()}>
/>
to retrive selected id's you can get from checked array
I am new in React and trying to build dynamic form. It seems to work fine. The problem is when i type the field values, they are shown in screen, but the value property of Textinput remain null. I tried to explore all options, and it came down to async of setState. Since i am new i do not know how to make a call back function which can populate the value property of the dynamic form fields.
I have not inlcuded all the code, just what i thought would be relevant to avoid burden.
thanks
sal
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
InputArray: [],
view_data: {
id: 0,
data: null
},
step: 0,
TotalItem: [],
item:
{
id: 0,
Email: null,
Password: null,
Address: null
}
}
};
///onCHANGE FUNCTIONS
EnterValue1 = (e) => {
e.persist();
let item = { ...this.state.item };
item.Email= e.target.value;
this.setState({ item: item });
EnterValue2 = (e) => {
e.persist();
let item = { ...this.state.item };
item.Password = e.target.value;
this.setState({ item: item });
EnterValue3 = (e) => {
e.persist();
let item = { ...this.state.item };
item.Address = e.target.value;
this.setState({ item: item });
//Dynamic form
Inputs = () => {
return (
<View >
<TextInput
placeholder="enter email"
onBlur={this.focusHandler}
value={this.state.item.Email}
onChange={this.EnterValue1}
style={{ borderWidth: 2, borderColor: 'skyblue', margin: 20 }}
/>
<TextInput
placeholder="Password"
onBlur={this.focusHandler}
value={this.state.item.Password}
onChange={this.EnterValue2}
style={{ borderWidth: 2, borderColor: 'skyblue', margin: 20 }}
/>
<TextInput
placeholder="Address"
onBlur={this.focusHandler}
value={this.state.item.Address}
onChange={this.EnterValue3}
style={{ borderWidth: 2, borderColor: 'skyblue', margin: 20 }}
/>
</View>
)
};
// Render Method
render() {
return (
<View style={{ flex: 1, marginTop: 20 }}>
<ScrollView style={styles.scrollView} keyboardShouldPersistTaps='always' >
{this.state.InputArray.map((item, index) => (
//using highlight because it doenst pass on its effect to children, opacity does
<View key={index} onPress={() => this.viewPress(index)}>
<TouchableOpacity onPress={() => this.viewPress(index)}>
{item.data}
{this.state.step === 0 ?
<View style={styles.container}>
<View style={{ flex: 1 }} >
<Button type='button' style={{ flex: 1, backgroundColor: 'red' }} title="add" onPress={this.add} />
</View>
</View>
:
<View style={styles.container}>
<View style={{ flex: 1 }} >
<Button type='submit' style={{ flex: 1, backgroundColor: 'red' }} title="add" onPress={this.add} />
</View>
<View style={{ flex: 1 }}>
<Button type='button' style={{ flex: 1, backgroundColor: 'red' }} title="Remove" onPress={() => this.remove(index)} />
</View>
</View>
}
</TouchableOpacity>
</View>
))
}
</ScrollView>
<View style={styles.container}>
<View style={{ flex: 1 }}>
<Button type='submit' style={{ flex: 1, backgroundColor: 'blue' }} title="submit" onPress={this.submit} />
</View>
</View>
</View>
);
}
}
EnterValue3 = (e) => {
e.persist();
let item = { };
this.setState({ item: {...this.state.item, address: e.target.value });
}
Replace all your function with spread operator rather than directly assigning into the object.
Try this and check
EnterValue1 = (e) => {
e.persist();
this.setState({
item: {
...this.state.item,
Email: e.target.value,
}
});
}
Note: Your whole code may help much to debug your issue
Just in case for someone interested. This may not be the best solution. As this is my first project in react native.
Although i was not able to get the values prop using this.state, and they remained null. For my dynamic form, i made a function containing my Views/textinput with an index argument, provided by my map function(which iterates over an array that has length equal to number of forms added). I used onChageText method and in setState used a callback to save the typed values in an object with an id, that needs to be equivalent to the index of my dynamics mapped form. Using index of object of arrays, values=this.state.object[index],values, is saved in dynamic form.
It still did not populate the values prop, but it sure did maintain the typed content in the front end of the previous form when i add new form.
Hi i'm new in React Native.
I am trying to create two columns layout with space beetween using react native component called flatList.
Here is my view Code:
<View style={styles.container}>
<FlatList
data={db}
keyExtractor={ (item, index) => item.id }
numColumns={2}
renderItem={
({item}) => (
<TouchableWithoutFeedback onPress ={() => showItemDetails(item.id)}>
<View style={styles.listItem}>
<Text style={styles.title}>{item.name}</Text>
<Image
style={styles.image}
source={{uri: item.image}}
/>
<Text style={styles.price}>{item.price} zł</Text>
</View>
</TouchableWithoutFeedback>
)
}
/>
</View>
Here is styles:
container: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
padding: 10,
marginBottom: 40
},
listItem: {
maxWidth: Dimensions.get('window').width /2,
flex:0.5,
backgroundColor: '#fff',
marginBottom: 10,
borderRadius: 4,
},
And result is two columns but without space between.
Could you help me resolve this problem ?
You can give the item itself a width value of 45%. Also, flatlist has a property called columnWrapperStyle that you can give the value justifyContent: 'space-between.
Heres an example:
<FlatList
columnWrapperStyle={{justifyContent: 'space-between'}}
data={ApiData}
numColumns={2}
renderItem={({item}) => {
return (
<item style={{width: '45%'}} />
);
}}
/>
Use ItemSeparatorComponent for render a compontent between items
Docs: Rendered in between each item, but not at the top or bottom.
<FlatList
data={arrayOfData}
horizontal
ItemSeparatorComponent={
() => <View style={{ width: 16, backgroundColor: 'pink' }}/>
}
renderItem={({ item }) => (
<ItemView product={item} />
)}
/>
Preview in horizontal list
If list is vertical and suppose columnCount is 2
You have to give the styles.container to the contentContainerStyle propety of Flatlist, like so:
<FlatList
data={db}
keyExtractor={ (item, index) => item.id }
contentContainerStyle={styles.container}
numColumns={2}
renderItem={
({item}) => (
<TouchableWithoutFeedback onPress ={() => showItemDetails(item.id)}>
<View style={styles.listItem}>
<Text style={styles.title}>{item.name}</Text>
<Image
style={styles.image}
source={{uri: item.image}}
/>
<Text style={styles.price}>{item.price} zł</Text>
</View>
</TouchableWithoutFeedback>
)
}
/>
Just add some margin to the style of the list Item.
listItem: {
margin: 10,
}
How to create two columns with equal spacing between items:
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={(item) => item.id}
horizontal={false} // you must include this line when using numColumns [per the documentation][1]
numColumns={2} // creates two columns
key={2} // add key to prevent error from being thrown
columnWrapperStyle={{justifyContent: 'space-between'}} // causes items to be equally spaced
>
Also, this will set each column to 1/2 the screen width:
const styles = StyleSheet.create({
item: {
flex: 1/2,
}})
I haven't used this library, but adding padding: 10 to listItem styles should help.
Based on your example it looks like you can add a margin to your list item styles:
listItem: {
maxWidth: Dimensions.get('window').width /2,
flex:0.5,
backgroundColor: '#fff',
marginBottom: 10,
borderRadius: 4,
margin: 18,
},
Keep in mind that this is equivalent to doing:
listItem: {
maxWidth: Dimensions.get('window').width /2,
flex:0.5,
backgroundColor: '#fff',
marginBottom: 10,
borderRadius: 4,
marginTop: 18,
marginBottom: 18,
marginRight: 18,
marginLeft: 18,
},
Customize to your liking or spec :)
Assuming your items are flex:1 and no width specified. You can wrap your renderItem with another view that adds the padding if needed
function columnWrappedRenderItemFunction<ItemT>(
renderItem: ListRenderItem<ItemT>,
numColumns: number,
space: FlatListProps<ItemT>["space"],
numberOfItems: number
): FlatListProps<ItemT>["renderItem"] {
return function columnWrappedRenderItem({
index,
...props
}: Parameters<ListRenderItem<ItemT>>[0]): ReturnType<ListRenderItem<ItemT>> {
const needsGapOnLeft = index % numColumns !== 0;
let extraItems = 0;
if (index === numberOfItems - 1) {
extraItems = (numColumns - (numberOfItems % numColumns)) % numColumns;
}
if (needsGapOnLeft) {
return (
<>
<View style={{width:space}} />
{renderItem({ index, ...props })}
{Array.from({ length: extraItems }, (_, k) => (
<View key={"extra_" + k} style={{marginLeft:space, flex:1}} />
))}
</>
);
} else {
return (
<>
{renderItem({ index, ...props })}
{Array.from({ length: extraItems }, (_, k) => (
<View key={"extra_" + k} marginLeft={space} style={{flex:1}} />
))}
</>
);
}
};
}
e.g.
function myRenderItem() { ... }
...
return (<FlatList
...
data={data}
renderItem={
numColumns === 1
? renderItem
: columnWrappedRenderItemFunction(
renderItem,
numColumns,
space,
data.length
)
}
numColumns={numColumns}
ItemSeparatorComponent={() => <View style={{height: space}} />}
/>);