FlatList data modification inside rendered FlatList item - javascript

I am currently trying to make this "project" work.
demo img
https://codesandbox.io/s/flatlisttesting-eiw0x
Expected behaviour:
a) clicking on element of FlatList should change their state resulting in the CheckBox being checked
b) clicking the "Select All" TouchableOpacity should result in all of the items' checkboxes being checked and clicking the TouchableOpacity again afterwards should uncheck the checkboxes
Result:
a) works as intended
b) When I click on an element (checking the CheckBox) and then try pressing the TouchableOpacity, the CheckBoxes are indeed checked, but when I click on the TouchableOpacity again it only unchecks the CheckBoxes that weren't previously checked(checked->unchecked)
Could anyone possibly shed some light on this problem?
Thanks in advance

It is generally not a good idea to keep a separate state inside the component, and also use another external data source, for a single data source. Here, your only data source is your array. So for a better convention, the only source of your FlatList should be the data you pass. So if you remove the extra state operations inside the CustomItem component, it will work as expected:
import { TouchableOpacity, View, Text, CheckBox } from "react-native";
import { useState } from "react";
export default function CustomItem({
item,
flatListData,
setFlatListData
}) {
function handlePress() {
setFlatListData(
flatListData.map((element) => {
if (item.id === element.id) {
return { ...item, isDone: !item.isDone };
}
return element;
})
);
}
return (
<TouchableOpacity onPress={handlePress} style={{ flexDirection: "row" }}>
<Text style={{ marginRight: 10 }}>{item.text}</Text>
<CheckBox value={item.isDone} onPress={handlePress} />
<Text>{JSON.stringify(item)}</Text>
</TouchableOpacity>
);
}
By doing that, the CustomItem will only rely on the data source and not need extra conditional renderings inside itself.
However, I also have one suggestion. Currently your Select All button does not work like a select all, but rather works like a toggle button. I would suggest you to modify it, so that it will select all if all items are not selected, and only uncheck all if all items is selected. It's up to you of course but the name and function does not look consistent.

Related

How to get the value of selected expo-checkbox in a loop react native

Please i need help trying to get the value/state of each selected checkbox in my react native project.
What I'm trying to do actually is to click on a button that navigates to "SelectProducts" screen. then the screen shows a list of items to select using checkboxes. I put the checkbox I imported from expo in a loop like the following:
import React, {useState, useEffect} from 'react'
import { StyleSheet, Text, View, Alert, Image, ScrollView, TouchableOpacity } from 'react-native';
import {useNavigation} from '#react-navigation/native';
import Checkbox from 'expo-checkbox';
const SelectProducts = ({route}) => {
const navigation = useNavigation();
const [checkedBox, setCheckedBox] = useState([]);
const [itemList, setItemList] = useState([]);
{itemList.map((item, index) => (
<View key={item.id} style={styles.checkboxContainer}>
<Checkbox
value={checkedBox[index]}
onValueChange={() => {
let checkedBox = [];
checkedBox[index] = !checkedBox[index];
setCheckedBox(checkedBox);
// console.log(setCheckedBox(checkedBox));
}}
color={checkedBox ? '#800080' : undefined}
style={styles.checkbox}
/>
</View>
))}
}
export default SelectProducts;
The code above is just a part of the entire code in the "SelectProducts" screen where I'm having issues. Please let me know what I'm not during right here.
So, after selecting the checkboxes for the items I want to include when recording a sales order, the system should get the price, item name, and picture to send back to the previous screen in order to calculate the total sum, etc. when done with the item selection.
But the result I'm getting is very weird. There is now a list of items with checkboxes as expected, but once I select one of the checkboxes, then try to select another one, the previous checkbox will be unselected automatically for the current one to be selected. The checkbox selection is behaving exactly like normal radio buttons that only accept one input at a time. Meaning that my checkbox implementation isn't allowing multiple selections. This is the main challenge I'm facing at the moment.
I have even tried to print out the output of the value when selected but it's showing 'undefined'. I'm so confused here. I know this is simple to some of the developers here but I'm quite finding it hard to implement. It has already taken me some days now. Please help. Thanks!
PS: I'm currently using this guy's solution How to handle checkbox in loop react native . He used a class component implementation while I used a function component. But it's not working for me. Don't know why. Please kindly help me look into it.
This might help
itemList.map((item, index) => (
.....
<Checkbox
...
onValueChange={() => {
const newCheckedBox = [...checkedBox];
newCheckedBox[index] = !newCheckedBox[index];
setCheckedBox(newCheckedBox);
}}
...
/>
....
))

How to preserve native animation of Switch?

I'd like to create a basic "setting toggle" component, with Title and Subtitle on the left, and a Switch on the right. I'd like to be able to switch the toggle when the whole component is clicked, not just when the switch is.
In order to achieve this is wrapped the component in a Touchable and execute the supplied onValueChange callback, so the container component can handle the state change of the switch.
export default function SettingToggle({
title,
subtitle,
toggled,
onValueChange,
}) {
return (
<TouchableWithoutFeedback
style={styles.container}
onPress={() => onValueChange(!toggled)}
>
<View>
<Text style={styles.title}>{title}</Text>
<Text style={styles.subtitle}>{subtitle}</Text>
</View>
<Switch
value={toggled}
onValueChange={value => onValueChange(value)}
></Switch>
</TouchableWithoutFeedback>
)
}
Now when I click the Switch, it animates nicely to the other value, but when click the component, the whole component redrawn with the new value of {toggled}, thus on the UI it feels like the switch is instantly changing to the other value.
Question 1: How could I preserve the animation even when the component is clicked, and not just the Switch?
Question 2: From where does React know, that it doesn't need to redraw the view when only the Switch is clicked? The render() method is called, as the parent component's state changes with the onValueChange call, so the SettingToggle is rerendered with a new {toggled} value. I assume the view is "recreated" but under the hood React probably isn't changing the view in the hierarchy with the newly created one, as it somehow knows that it is not needed. How does this work?

React Native get Clicked(pressed) component's attribute

I'm making some dynamic CardView which can show videos like as Facebook.
But there's problem when I press share button and comment button.
Because I need the clicked button's(share, comment) index.
So I think I can use the key prop of button.
I make buttons with touchableOpacity, then I'll set key of touchableOpacity
like this.
<TouchableOpacity
key = {some index}
>
some stuffs
</TouchableOpacity>
Then, I want to get pressed component's attr value( key value at here )
I can find the key value at
ReactNativeComponentTree.getInstanceFromNode(event.nativeEvent)
But this data always show my key is null.
There's no way to get clicked Component's key value?
Thanks for reading.
If you really need the index in the onPress handler, you can create a new inline function and pass along the index instead.
Example
<TouchableOpacity
key={someIndex}
onPress={() => this.handlePress(someIndex)}
>
some stuff
</TouchableOpacity>

React Native Elements ListItem won't show switch button

I'm trying to create a settings menu for a react native project I am working on, and for the majority of my UI I am using react native elements. One of the settings I need is a boolean value, so I want to use a switch in order to change that value. However I can not get the switch to even show up on the list item.
Here are my imports in my settings.js file:
import React from 'react';
import { Switch, Dimensions, StyleSheet, Text, View } from 'react-native';
import {ListItem, Input, Button } from 'react-native-elements';
When I try to create a a List Item with a switch, Like so:
<ListItem
switch
title="Active"
switched = {this.state.active}
/>
I get an error that says: "TypeError: IN this environment the sources for assign MUST be an object. This error is a performance optimization and not spec compliant"
If I try to create a ListItem like this:
<ListItem
switchButton
title="Active"
switched = {this.state.active}
/>
The item shows up but there is no switch. What am I missing?
First i think there is no switch props in Lists.
Second if you need to display the switchButton you need to add the hideChevron prop as well.
Example:
<List>
<ListItem
switchButton
title=":( Where is my switch?"
onSwitch={e => console.warning(e)}
/>
<ListItem
switchButton
hideChevron
title=":) Here it is!"
onSwitch={() => {}}
/>
</List>

Semantic UI React, Dropdown Selection

Please take a look at my code for Dropdown,
I'm using the semantic ui react dropdown on an EditProfile component. I have pasted a sample code here, https://codesandbox.io/s/m4288nx4z8, but I could not get it to work because I'm not very familiar with functional components in React, I've always used Class component. But you can check the full code for the whole component below in the github gist.
https://gist.github.com/mayordwells/b0cbb7b63af85269091f1f98296fd9bb
Please, I need help on inserting values from multiple select options of a Dropdown into the Database and also a way to display that back upon viewing the profile edit page again.
I'm using semantic-ui-react in react + rails app.
Also when I insert a value using a normal drop down without multiple select, the value gets persisted into the database.
<Dropdown
placeholder='Select Country'
fluid
search
selection
options={countryOptions}
name='country'
defaultValue={this.state.extraInfo.country}
onChange={(e) => this.handleExtraInfoChange('country', e)}
/>
This code handles change for the dropdown elements.
handleExtraInfoChange = (name, event) => {
let value;
if (event.target.value !== undefined) {
value = event.target.value;
} else {
value = event.target.textContent;
}
let newExtraInfo = Object.assign(this.state.extraInfo, { [name]: value })
this.setState({ extraInfo: newExtraInfo});
}
But when I visit the page again, I get a white blank in the input box. Here's a screen pic for that. When I comment out the defaultValue or value property(i have tried with defaultValue and value), the white blank disappears, but the value picked by a user is also not seen.
Please advice what is a possible solution to this misbehavior? And what is the best way to insert multiple values into the Database?
Thanks in advance for your time.
A functional component does not have state, it's used for composition; you want to store state, so you either have to create a Component class or you need an external state container like redux.

Categories