Мерцающие компоненты при анимации maxHeight ScrollView (реагировать-нативный)

У меня есть элементы списка дел, которые можно разворачивать и сворачивать, нажимая соответствующую кнопку.

При нажатии на кнопку EXPAND регулируется высота анимированного ScrollView. От 0 до 100 при расширении и от 100 до 0 при сворачивании. Когда мы разворачиваем два списка-объекта одновременно, экран начинает мерцать.

Вот код одного единственного todo-элемента (он сокращен, значит кнопки DONE в нем нет):


import React, { useState, useRef, memo } from 'react';
import { Animated, Text, View, Button, ScrollView } from 'react-native';
import longText from '../data/data';

const ListObject = (props) => {
    
    //Object Expand and Collapse feature
    const expandValue = useRef(new Animated.Value(0)).current;
    const [expandState, setExpand] = useState(false);

    const expandAnimation = () => {
        Animated.timing(expandValue, {toValue: 100, duration: 1000, useNativeDriver: false}).start();
        setExpand(true);
    }
    
    const collapseAnimation = () => {
        Animated.timing(expandValue, {toValue: 0, duration: 1000, useNativeDriver: false}).start();
        setExpand(false);
    }


    return (
        <View style = {{ margin: props.margin }}>
            <View style = {{
               flexDirection: 'row',
               backgroundColor: 'grey',
               borderRadius: 10, 
            }}>

                <Button title='EXPAND' style = {{
                    flex: 1,
                    backgroundColor: 'blue',
                }}
                onPress = { expandState ? collapseAnimation : expandAnimation }
                />
            </View>

            <Animated.ScrollView style = {{ 
                flex: 1,
                paddingHorizontal: 40,
                backgroundColor: 'grey',
                borderRadius: 10,
                maxHeight: expandValue
             }}>
                <Text>{ props.text }</Text>              
            </Animated.ScrollView>

        </View>
    );


}


export default memo(ListObject);

Вот код для приложения. Чтобы создать коллекцию всех элементов todo, я сопоставляю список и назначаю ключ каждому элементу:

mport React, { useRef, useState } from 'react';
import { Animated, StyleSheet, ScrollView, Text, View, SafeAreaView, Button } from 'react-native';
import longText from './src/data/data';
import ListObject from './src/components/list-object'

const styles = StyleSheet.create({
  safeContainer: {
    flex: 1.2
  },
  headerContainer: {
    flex: 0.2,
    flexDirection: 'column',
    justifyContent: 'center',
    backgroundColor: 'lightblue',
  },
  headerFont: {
    fontSize: 50,
    textAlign: 'center',
  },
  scrollContainer: {
    flex: 1 
  }
});


const App = () => {


    const numbers = [1,2,3,4,5,6,7,8,9];
    const listItems = numbers.map((number) => 
      <ListObject key = {number.toString()} margin = {10} headerText='I am the header of the to-do element' text = {longText} />
    )



  return (

    <SafeAreaView style = { styles.safeContainer } >
      
      <View style = { styles.headerContainer }>
          <Text style = { [styles.headerFont] }>LIST MAKER</Text>
      </View>

      <ScrollView style = { styles.scrollContainer }>

      {listItems}

      </ScrollView>
    </SafeAreaView>
  
  
  );

};

export default App;

Я не ожидал мерцания. Мерцание появляется также на моем физическом устройстве Android. Я искал похожие проблемы и проверял другие библиотеки, как они это реализуют.

2
0
89
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Для этого можно использовать react-native-collapsible

import Accordion from 'react-native-collapsible/Accordion';

const [activeSections, setActiveSessions] = useState([])

const _updateSections = (activeSections) => {
    setActiveSessions(activeSections.includes(undefined) ? [] : activeSections)
  }

<Accordion
        sections = {data}
        activeSections = {activeSections}
        duration = {400}
        renderHeader = {_renderHeader}
        renderContent = {_renderContent}
        onChange = {_updateSections}
        touchableComponent = {TouchableOpacity}
        renderAsFlatList = {true}
        expandMultiple = {true}
      />

Для лучшей производительности и плавного опыта используйте этот.

Спасибо за ваш ответ. Я хотел бы реализовать это самостоятельно. Я начал с реакции неделю назад и хотел бы понять детали.

Christel-is-creative 31.10.2022 12:41

Вы можете найти весь пример здесь github.com/oblador/react-native-collapsible/blob/master/Exam‌​ple/…

Nensi Kardani 31.10.2022 14:04
Ответ принят как подходящий

Ошибку нашел сам, это ошибка новичка.

Вместо того, чтобы управлять состоянием компонента в самом компоненте, мне пришлось поднимать состояние до родителя.

Вот ссылка на обучающий документ ReactJS.

Другие вопросы по теме