简体   繁体   中英

How to animate reordering of reducer array state in React Native LayoutAnimation

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM