1

当 Redux reducer 的属性更新时,如何使用 React Native LayoutAnimation 实现重新排序动画?

players在 Redux 减速器中有一个数组,看起来像这样:

在此处输入图像描述

玩家减速器.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
}];

当 reducer 通过 websocket 响应获取更新时,相应数组对象上的 score 属性会发生变化。我可以使用 Chrome redux 浏览器插件确认每个对象状态保持不变,并且显示的差异证明了这一点;

在此处输入图像描述

当 reducer 更新我的功能组件的状态时,我playersReducer.players使用函数对数组重新排序,sort以按分数对玩家进行排序,如下所示:

let players = [...props.playersReducer.players];

return (
    {players
        .sort((player1, player2) => (player1.score > player2.score) ? -1 : 1 )
        .map((player, i) => {
           return (
              // player UI rendered here   
           )

我已经LayoutAnimation.configureNext()在函数组件的主体中进行了设置,它确实成功地渲染了一个新项目,该项目从另一个 reducer 中添加了数组,这证明了 LayoutAnimation 正在工作;

    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"}
        })
        
    });

如何使用LayoutAnimation动画播放器组件上的重新排序效果?我正在尝试实现这样的目标:

在此处输入图像描述

4

1 回答 1

1

您可以使用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',
  },
});

你可以在这里查看演示。

于 2020-12-16T11:59:03.687 回答