How can I achieve a reordering animation using React Native LayoutAnimation when a Redux reducer's property is updated?
I have a players
array in a Redux reducer, looks something like this:
playersReducer.players:
[{
"uuid": "681b04b5-5b39-4c6c-b21d-8a8a2240a0c7",
"name": "Tom",
"score": 190,
"online": false,
"isMe": null
}, {
"uuid": "02531db4-e61d-4754-bb4a-fef1a696bef4",
"name": "Dick",
"score": 10,
"online": false,
"isMe": null
}, {
"uuid": "51420a54-7563-4cd2-adf3-ccefc1b6ffca",
"name": "Harry",
"score": 170,
"online": false,
"isMe": null
}];
When a reducer gets an update via a websocket response the score property changes on the appropriate array object. I can confirm with the Chrome redux browser plugin that each object state is remaining immutable and the diff shown proves that;
When the reducer updates my functional component's state I reorder the playersReducer.players
array with the sort
function to order the players by score as so:
let players = [...props.playersReducer.players];
return (
{players
.sort((player1, player2) => (player1.score > player2.score) ? -1 : 1 )
.map((player, i) => {
return (
// player UI rendered here
)
I've setup LayoutAnimation.configureNext()
in the body of the function component, which does successfully render a new item being added the array from another reducer which proves LayoutAnimation is working;
const isFirstRender = React.useRef(true);
React.useEffect(() => {
if (isFirstRender.current) {
isFirstRender.current = false;
return;
}
/*business logic for component did update*/
LayoutAnimation.configureNext({
...LayoutAnimation.Presets.easeInEaseOut,
create: {property: "scaleXY"},
delete: {property: "scaleXY"},
update: {property: "scaleXY"}
})
});
How can I use LayoutAnimation
to animate a reordering effect on my player components? I'm trying to achieve something like this:
You can achieve this goal using Transitioning View
.
import React, { useRef, useState } from 'react';
import { Button, SafeAreaView, FlatList, StyleSheet, Text, View } from 'react-native';
import { Transition, Transitioning } from 'react-native-reanimated';
const transition = (
<Transition.Together>
<Transition.Change durationMs={500} />
</Transition.Together>
);
export default App = () => {
const [data, setData] = useState([2, 4, 3, 1]);
const ref = useRef();
return (
<SafeAreaView style={{ flex: 1 }}>
<Transitioning.View ref={ref} transition={transition}>
<FlatList
data={data}
keyExtractor={(item) => item.toString()}
renderItem={({ item }) => {
return (
<View style={styles.item}>
<Text style={styles.itemText}>{item}</Text>
</View>
);
}}
/>
</Transitioning.View>
<Button
title="Reorder"
onPress={() => {
ref.current.animateNextTransition();
const sortedData = [...data];
sortedData.sort();
setData(sortedData);
}}
/>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
item: {
width: '100%',
height: 100,
backgroundColor: 'red',
marginVertical: 10,
justifyContent: 'center',
alignItems: 'center',
},
itemText: {
fontSize: 21,
color: '#fff',
},
});
You can check the demo here.