oblador / react-native-collapsible

Animated collapsible component for React Native, good for accordions, toggles etc
MIT License
2.44k stars 451 forks source link

Various issues, is this library still maintained? #390

Open jackdewhurst opened 3 years ago

jackdewhurst commented 3 years ago

I've been struggling with multiple issues using this library. After hours of trial and error, forking the library and tweaking I decided it was easier to just write something from scratch using functional components and hooks.

Below is a like-for-like single file replacement for Collapsible if anyone is interested using no third party dependencies. It supports iOS/Android/Web and works great so far including nested support.

// Collapsible.js

import React, { useRef, useState, useEffect } from 'react';
import { StyleSheet, View, Animated, Easing } from 'react-native';

export default function Collapsible(props) {
  const content = useRef();
  const mounted = useRef();

  const [collapsed, setCollapsed] = useState(props.collapsed);
  const height = useRef(new Animated.Value(props.collapsedHeight)).current;
  const [contentHeight, setContentHeight] = useState(0);

  function onContentLayout(event) {
    const newHeight = event.nativeEvent.layout.height;
    if (!collapsed && newHeight != contentHeight) {
      update(true)
    }
    setContentHeight(newHeight);
  }

  function update(force = false) {
    if (!force && props.collapsed === collapsed) return;
    const duration = props.duration ?? 200;
    const collapsedHeight = props.collapsedHeight
    const toValue = props.collapsed ? collapsedHeight : contentHeight;

    Animated.timing(height, {
      easing: props.easing ?? Easing.linear,
      toValue,
      duration: duration,
      useNativeDriver: props.useNativeDriver ?? false
    }
    ).start(() => setCollapsed(props.collapsed));
  }

  useEffect(() => {
    if (!mounted.current) {
      mounted.current = true;
    } else {
      update();
    }
  });

  return (
    <Animated.View
      style={[styles.main, props.style, { height }]}
      pointerEvents={!props.enablePointerEvents ? 'none' : 'auto'}>
      <View style={[styles.content, { minHeight: props.collapsedHeight }]}
        ref={content}
        onLayout={onContentLayout}>
        {props.children}
      </View>
    </Animated.View>
  )
}

const styles = StyleSheet.create({
  main: {
    width: '100%',
    overflow: 'hidden'
  },

  content: {
    width: '100%'
  }
})
wmonecke commented 3 years ago

This ain't working for me. What was causing an issue for me was using { flex: 1 } in children.

oblador commented 3 years ago

1.6.0 was just released with a lot of bug fixes and new features, can you verify that your issues persist. If so would you mind giving me a minimal example to reproduce them?

wqxwqx commented 2 years ago

can i ask how to use this ?It didn't respond to my program @jackdewhurst