How to dinamically update the value coming from useAnimatedStyle - Reanimated 2 - react-native

Say that I have a component where I create child components based on the number of elements passed from the parent ( think of it as a page indicator, for example ).
What I would like to do, is to animate the transition between these dots (their backgroundColor) depending on which one is active.
I have tried in a few ways to match the current value to the index of the child element, however, since I don't have the index beforehand, my attemps have failed.
I am posting the basic component down there without my fail attemps to animate it so it illustrates better what I am talking about.
How would one go about doing that in reanimated 2?
const component = ({active, amountOfDots}) => {
const dotsArray = Array(amountOfDots).fill(0);
return (
<View style={{}}>
{dotsArray.map(() => {
return <Animated.View style={{}} />;
})}
</View>
);
};

Related

Return JSX Is Not Updating On State Change From Some Reason

So like the title states I have it setup so that I want to display a loading text or something simple while I wait for my array to get loaded up with data from a local array.
I have a simple array at the top of my class with Name, Id and Image. I than load these into an array I called items and load into another array called random items.
When I run the code normally nothing gets displayed due to the array being empty. I understand that and have tried to create this workaround but does not appear to be working.
return (
<LinearGradient colors={["#FF8A8A", "#DC143C"]} style={{ flex: 1 }}>
<View>
{dataLoaded ? (
<View>
<Text>Loading...</Text>
</View>
) : (
items.map((item, i) => {
<MatchingDisplay
key={i}
listItem={item}
randItem={randItems[i]}
checkChoice={checkChoice}
/>;
})
)}
</View>
</LinearGradient>
);
After my function runs and the array is loaded up I make a state change to dataLoaded and change it to the boolean value True. For some reason my return method is not updating and displaying the items mapped out using the MatchingDisplay component.
I am not using any asynchrous functions as from what I understand it should just update automatically.
Any and all help is appreciated thanks!
Your conditional is flipped.
When dataLoaded is false, the empty array is displayed. When it’s true, the loading text is displayed. Flipping this to !dataLoaded should fix the issue.

Onclick button, state doesn't change

I'm having some troubles understanding the code.
Basically if I do this:
<Text onPress={() => console.log('123')} >123</Text>
,
and I click on the text, it logs me 123 each click.
But I'm doing a dialer app. Basically having a component Tile (representing a single number, also with secondary option (but that will be dealt with later)).
So as I'm including my (currently only single one) Tile in App.js, I want onPress event to call function that changes state of currently dialed number. So if user clicks 3 times on '1', I want the final string to be 111.
The thing is, I can see that the handleNumber() function is called once after running code and never again after clicking on the number, therefore never changing state, not logging anything.
App.js Tile implementation:
const [getNumber, setNumber] = useState();
const handleNumber = (newChar) => {
console.log(newChar);
setNumber(newChar);
}
<Tile onPress={() => handleNumber('1')} style={styles.tile} firstChar={'1'} secondChar={'✉'}/>
Tile.js:
const Tile = (props) => {
return (
<TouchableOpacity onPress={props.onPress()}>
<View>
<Text style={styles.mainChar}>{props.firstChar}</Text>
{props.secondChar ? <Text style={styles.secondChar}>{props.secondChar}</Text> : null}
</View>
</TouchableOpacity>
)
}
One more thing:
As you can see in App.js::handleNumber(),
the implementation is currently wrong, because the final number will always be just the new single number, instead of appending it to the end of string.
But if I wanted to do smth like setNumber(getNumber + newChar), it would give Maximum update depth exceeded error.
The thing here is the way that you're passing the onPress prop to TouchableOpacity. See, you're calling the props.onPress function instead of just passing it to the component, which causes the function to be executed when the component renders (or rerenders).
You should be fine just by using <TouchableOpacity onPress={props.onPress}> and then setNumber(getNumber + newChar) will be fine as well.
As a side note, you could initialize your App.js state with the '1' string that you wish to be your initial value (const [getNumber, setNumber] = useState('1')), and then the Tile component can receive getNumber directly.

React Native FlatList ListEmptyComponent always showing even if not empty

I'm browsing through StackOverflow in search of someone experiencing my same issue, however couldn't find much. I'm fetching flatlist data from backend and i need the empty text placeholder component to disappear when flatlist is not empty, however it always stays there and never disappears even when data is correctly fetched in the flatlist. How can i solve this?
Ps. When assigning dummy data to the flatlist, this issue does not happen.
<FlatList
ListEmptyComponent={() => (<Text style={styles.emptyListText}>No upcoming trips to show.</Text>)}
data={trips}
renderItem={({ item }) => <MyTripsPostItem post={item} onPress={() => navigation.navigate("Post Screen")}
/>}
/>
What I do is that I check if the query is loading and if it is not then I show my View ListEmptyComponent.
ListEmptyComponent={
!isLoading && (
<View style={styles.containerEmptyList}>
// things
</View>
)
}
I use react-query which provide a "isLoading" variable but you can do the same in your function query with useState
Edit : Also the function () => is not needed for that props.
Use trips.length instead of trips.
// checks if trips size is more than 0
!trips.length && <ListEmptyComponent />
while
// checks if trips is undefined or null
trips && <ListEmptyComponent />
In your case, I presume you set a default value to trips which is an empty array / [], so, it wasn't undefined or null.

What is the best practice in React Navigation to update a list of items after the item is altered?

Here is the scenario :
I have a bottom tab with two tabs : Actions and People
One Action always belong to one Person
On the People tab, I can view, add and edit an Action to do
If I am in the stack People > Person from where I edit an action,
How can I update only the Action row in the Actions list ? What is the best practice ?
The best would be to not use redux for this if possible, in order to make a good use of react navigation's redux...
Tell me if it's not clear enough
It might help to see some example code, but generally speaking you want to move the information from the "Person" screen all the way up to a common parent and then back down to a child (the Action screen/tab).
Here's some pseudo code with only 1 action, where changing the action on a Person Screen will ultimately update that action in the Action Tab:
function Root({ }) {
const [action, setAction] = useState('initialAction')
return (
<View >
<PeopleTab setAction={setAction} action={action} />
<ActionTab setAction={setAction} action={action} />
</View>
);
}
function PeopleTab({ setAction, action }) {
return (
<View >
<PersonScreen setAction={setAction} action={action}/>
</View>
);
}
function PersonScreen({ setAction, action }) {
return (
<View >
// handle setting the action here with some onPress={() => setAction('new action'))
</View>
);
}
function ActionTab({ setAction, action }) {
return (
<View >
// Handle displaying the action here {action}
</View>
);
}

What is renderRow ()

I went through React-Native docs to figure out what is renderRow() but for some reason I am unable to comprehend what does it say from Facebook React-Native docs
This what the official docs says
renderRow
(rowData, sectionID, rowID, highlightRow) => renderable
Takes a data entry from the data source and its ids and should return a renderable component to be rendered as the row. By default the data is exactly what was put into the data source, but it's also possible to provide custom extractors. ListView can be notified when a row is being highlighted by calling highlightRow(sectionID, rowID). This sets a boolean value of adjacentRowHighlighted in renderSeparator, allowing you to control the separators above and below the highlighted row. The highlighted state of a row can be reset by calling highlightRow(null).
[Question:] Can someone please explain me this with example?
ListView is deprecated, use FlatList instead with the equivalent renderItem method. This is responsible of the actual rendering of each row based on the data records:
const data = [
{ key: '1', label: 'foo' },
{ key: '2', label: 'bar' }
]
renderTheItem = ({item}) => {
return <Text>{item.label}</Text>
}
<FlatList
data={data}
renderItem={this.renderTheItem}
/>
And the rendered result will be something like this:
<View> --> coming from FlatList wrapper
<Text key="1">foo</Text> --> coming from the custom renderTheItem function
<Text key="2">bar</Text>
</View>
It is mandatory to either add a unique key prop for each data record, or define a keyExtractor function. Also important to destruct the item in the renderer function with ({item}) as it has other meta parameters as written in documentation of FlatList.
renderItem({ item, index, separators}) => {}