React Native get Clicked(pressed) component's attribute - javascript

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>

Related

FlatList data modification inside rendered FlatList item

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.

How to properly render a success message upon clipboard click and copy

I'm creating a color palette where I have a clipboard icon within a Tooltip component next to each color. On click it will copy the color's name onto the user's clipboard. When that happens, the Tooltip's message should change from "copy" to "copy success". I'm having issues trying to display the success message individually for each color.
All of you Tooltip components are using the same parent state this.state.copyMessage. If you click copy on one, that sets this.state.copyMessage to "copy success", and it gets rerendered for all other Tooltips. You need to be able to either:
identify who was clicked,
give state to each Tooltip,
add one state entry per tooltip.
I'd personally go with a way to identify who was clicked.
Global declaration
const PROMPT_MESSAGE = "Copy to clipboard"
const CLICKED_MESSAGE = "Copied!"
Set your state onClick
setState({ clickedColor: color.name });
Get the appropriate message for the specific color
const tooltipTitle = this.state.clickedColor === color.name
? CLICKED_MESSAGE
: PROMPT_MESSAGE
Pass in the title
<Tooltip title={tooltipTitle} placement="right">
</Tooltip>
There are many ways to work around this, and this is just one I find readable!
Try passing 'event' as a parameter to your onClick function and using the stopPropagation() method. Like so:
<Tooltip title={copyMessage} placement="right">
<span
onClick={(event) => {
event.stopPropagation()
copyNameToClipboard(color.name);
setState({
copyMessage: 'copy success',
});
}}
>
This should stop your event from 'bubbling up' to other components:
https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation

React Native: How to have change button title and onPress function based on the status of the object?

I have a list in which the user can add items with the 'Add' Button, and I want to make the 'Add' Button become the 'Delete' Button after the user click once. My thought is to set a boolean value for items to keep track of whether it is in the list, but how can I change the title and onPress function of the Button? What's the appropriate way to implement it in React Native? Thanks in advance.
You can keep your status of your object in state and your text and onPress function of your button will change automatically when your object status changed.
Something like this:
<TouchableOpacity onPress=(this.state.status ? () => addFunction() : () => deleteFunction())>
{(this.state.status) ? "Add" : "Delete"}
</TouchableOpacity>
And when user click on your item, just simply set status state
function itemClick() {
// Do something
this.setState({
status: false
})
}

Is there a way to call method when first item is picked in React Native Picker?

EDIT
functionToRedirect(itemValue) is a function that gets called when an item in the picker is selected and it redirects to a new screen prepopulating some values in the screen based on 'itemValue'.
However, functionToRedirect(itemValue) is not being called when the same value is selected which I assume is because the value didn't change and thus onValueChange() will not be fired.
Is there a way for me to call the functionToRedirect(itemValue) even when the value didn't change(i.e when the initial value is selected) to try and redirect to the new screen?
<Picker
style={styles.picker}
itemStyle={styles.pickerItem}
mode={"dialog"}
selectedValue={this.props.value}
onValueChange={(itemValue) => {
functionToRedirect(itemValue);
}
}>
{this.state.pickerItems}
</Picker>
How about using a custom picker? Nativebase, a custom implementation of ReactNative UI components can give you a customised flavour of the components.
They have implemented Picker using RN Picker as a wrapper around flatlist of items opened in a modal window through which you can select items accordingly.
The solution I came to was to pass selectedValue null such that the first displayed option in the dropdown is the dropdown title.
The solution looks like below
<Picker
style={styles.picker}
itemStyle={styles.pickerItem}
mode={"dialog"}
selectedValue={null}
onValueChange={(itemValue) => {
this.props.onChange(itemValue)
}}
>
{this.state.pickerItems}
</Picker>
which shows the picker title as the initial value of the dropdown as shown below

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?

Categories