Cómo animar la reordenación del estado de matriz de reductores en React Native LayoutAnimation

¿Cómo puedo lograr una animación reordenante usando React Native LayoutAnimation cuando se actualiza una propiedad de Redux reducer?

Tengo un players array en un reductor Redux, parece algo así:

enter image description here

jugadoresReducer.jugadores:

[{
    "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
}];

Cuando un reductor obtiene una actualización a través de una respuesta de websocket, la propiedad puntuación cambia en el objeto de array adecuado. Puedo confirmar con el plugin del navegador Chrome redux que cada estado objeto está siendo inmutable y el diff mostrado demuestra que;

enter image description here

Cuando el reductor actualiza el estado de mi componente funcional reordeno playersReducer.players array con el sort función para ordenar los jugadores por puntuación como así:

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

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

He preparado LayoutAnimation.configureNext() en el cuerpo del componente de función, que hace que un nuevo elemento sea añadido de otro reductor que demuestre que LayoutAnimation está funcionando;

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

¿Cómo puedo usar LayoutAnimation para animar un efecto reordenante en mis componentes de jugador? Estoy tratando de lograr algo como esto:

enter image description here

Pregunta hecha hace 3 años, 5 meses, 0 días - Por csscraftsman


3 Respuestas:

  • Usted puede lograr este objetivo utilizando 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 = (
      
        
      
    );
    
    export default App = () => {
      const [data, setData] = useState([2, 4, 3, 1]);
      const ref = useRef();
    
      return (
        
          
             item.toString()}
              renderItem={({ item }) => {
                return (
                  
                    {item}
                  
                );
              }}
            />
          
          
      );
    };
    
    const styles = StyleSheet.create({
      item: {
        width: '100%',
        height: 100,
        backgroundColor: 'red',
        marginVertical: 10,
        justifyContent: 'center',
        alignItems: 'center',
      },
      itemText: {
        fontSize: 21,
        color: '#fff',
      },
    });
    

    Puedes revisar la demo Aquí..

    Respondida el Dec 16, 2020 a las 11:03 - por codecanvas

    Votos positivos: 0 | Votos negativos: 0

  • Para lograr una animación al reordenar los jugadores en tu componente al actualizarse el estado del array de jugadores en Redux, puedes seguir los siguientes pasos:

    • Asegúrate de tener configurada la opción `useNativeDriver` en `true` en la configuración de `LayoutAnimation`. Esto es necesario para que las animaciones se ejecuten de manera suave y eficiente en React Native.
    • Dentro de tu componente de función, puedes usar un efecto de `useEffect` que se active cada vez que el array de jugadores cambie. En este efecto, puedes configurar la animación de LayoutAnimation antes de que se realice la actualización del estado.
    javascript
    const isFirstRender = React.useRef(true);
    
    React.useEffect(() => {
        if (!isFirstRender.current) {
            LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut, () => {
                // Lógica adicional después de la animación
            });
        } else {
            isFirstRender.current = false;
        }
    }, [props.playersReducer.players]); // Escucha cambios en el array de jugadores
    
    • Luego, dentro del `map` de los jugadores en tu JSX, puedes asignar una `key` única a cada jugador para que React pueda identificarlos correctamente durante las actualizaciones.
    • Asegúrate de que en tu `sort` estás utilizando el operador correcto para ordenar de manera ascendente o descendente según tus necesidades.

    Con estos pasos, deberías poder animar la reordenación de los jugadores en tu componente cuando se actualice el estado del array de jugadores en Redux. Recuerda también asegurarte de tener las librerías necesarias importadas para utilizar LayoutAnimation.

    Respondida el Dec 17, 2020 a las 10:58 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Paso 1: Crear una clave única para cada elemento de la lista

    Para que React Native LayoutAnimation funcione correctamente con listas reordenadas, cada elemento de la lista debe tener una clave única. En tu caso, puedes usar la propiedad uuid como clave:

    
    
    

    Paso 2: Usar LayoutAnimation.create() y LayoutAnimation.update()

    Cuando se actualiza la propiedad score de un jugador, desencadena una reordenación de la lista. Puedes usar LayoutAnimation.create() cuando se agrega un nuevo elemento a la lista y LayoutAnimation.update() cuando se actualiza un elemento existente:

    
    useEffect(() => {
      LayoutAnimation.configureNext({
        ...LayoutAnimation.Presets.easeInEaseOut,
        create: {
          type: LayoutAnimation.Types.easeInEaseOut,
          property: LayoutAnimation.Properties.scaleXY,
        },
        update: {
          type: LayoutAnimation.Types.easeInEaseOut,
          property: LayoutAnimation.Properties.scaleXY,
        },
      });
    }, [players]);
    

    Paso 3: Usar useAnimatedStyle()

    Para animar la reordenación, puedes usar useAnimatedStyle() de React Native Animated para transformar el estilo de los elementos de la lista:

    
    const animatedStyle = useAnimatedStyle(() => {
      return {
        transform: [{ scale: animatedScale.value }],
      };
    });
    
    return ;
    

    En este ejemplo, animatedScale es una variable animada que controla la escala del elemento.

    Paso 4: Animar animatedScale

    Cuando se actualiza un elemento de la lista, puedes animar animatedScale usando Animated.timing():

    
    Animated.timing(animatedScale, {
      toValue: 1,
      duration: 200,
      useNativeDriver: true,
    }).start();
    

    Esto animará la escala del elemento de 0 a 1 durante 200 milisegundos, creando un efecto de reordenación suave.

    Ejemplo de código completo:

    
    import { useAnimatedStyle } from 'react-native-reanimated';
    import { Animated } from 'react-native';
    
    const Player = ({ player }) => {
      const animatedScale = new Animated.Value(0);
    
      const animatedStyle = useAnimatedStyle(() => {
        return {
          transform: [{ scale: animatedScale.value }],
        };
      });
    
      useEffect(() => {
        Animated.timing(animatedScale, {
          toValue: 1,
          duration: 200,
          useNativeDriver: true,
        }).start();
      }, []);
    
      return ;
    };
    
    const PlayersList = ({ players }) => {
      LayoutAnimation.configureNext({
        ...LayoutAnimation.Presets.easeInEaseOut,
        create: {
          type: LayoutAnimation.Types.easeInEaseOut,
          property: LayoutAnimation.Properties.scaleXY,
        },
        update: {
          type: LayoutAnimation.Types.easeInEaseOut,
          property: LayoutAnimation.Properties.scaleXY,
        },
      });
    
      return players.map((player) => );
    };
    

    Respondida el Dec 17, 2020 a las 11:07 - por Gemini

    Votos positivos: 0 | Votos negativos: 0