0

I'm quite a new using React Native and I'm trying to display a component only if the internet connection is not reachable. When it is the component must disappear.

My problem is that this component must not be shown on the startup. If the connection is false, the component must be animate from out of the screen to his wanted position. Then if the connection state change to true, it must disappear to his initial position out of the screen.

I'm able to do that but it's always shown on startup.

Here is my code structure :

const HealthCheckStatus = (): Node => {
  const [status, setStatus] = useState(true);
  const netInfo = useNetInfo();

  useEffect(() => {
    if (netInfo.isInternetReachable != null) {
      setStatus(netInfo.isInternetReachable);
    }
  }, [netInfo.isInternetReachable]);


  const animatedStyles = useAnimatedStyle(
    () => ({
      transform: [
        {
          translateY: withSequence(withSpring(-100), withSpring(0, { stiffness: 65 })),
        },
      ],
    }),
    [],
  );

  const animatedStylesRemove = useAnimatedStyle(
    () => ({
      transform: [
        {
          translateY: withSequence(withTiming(0), withDelay(5000, withSpring(-100))),
        },
      ],
    }),
    [],
  );

  const getStatusLabel = () => {
    switch (status) {
      case false:
        return 'connection failed'
      case true:
        return 'connected'
      default:
        return 'connected';
    }
  };

  return (
      <Animated.View style={[{}, !status ? animatedStyles : animatedStylesRemove]}>
        <HealthStatusContainer>
          <Dot status={status} />
          <StatusLabel>{getStatusLabel()}</StatusLabel>
        </HealthStatusContainer>
      </Animated.View>
  );
};

export default HealthCheckStatus;

My problem here is that I'm forced to use two different animations depending on the state. How can I stop the animation until a state change? Or if the state changes, play the animation backward. If the state is false, do that ... then if the state becomes true (after it was false) do that in reverse.

Thanks a lot for your help.

I've tried to use conditional rendering in the animated style but it's not possible.

ejuhjav
  • 2,660
  • 2
  • 21
  • 32

1 Answers1

0

I think you are looking for useSharedValue. useAnimatedStyle works smoothly with shared values, and as a bonus you can scrap animatedStylesRemove entirely:

 const animationDriver = useSharedValue(0);

  useEffect(() => {
    const newStatus = netInfo.isInternetReachable;
    if (newStatus !== null) {
      setStatus(newStatus);
    }
    animationDriver.value = !newStatus
      ? withSequence(withSpring(-100), withSpring(0, { stiffness: 65 }))
      : withSequence(withTiming(0), withDelay(5000, withSpring(-100)));
  }, [netInfo.isInternetReachable]);

 const animatedStyles = useAnimatedStyle(() => {
    return {
      transform: [
        {
          translateY: animationDriver.value,
        },
      ],
    };
  }, [animationDriver.value]);

Demo

PhantomSpooks
  • 2,877
  • 2
  • 8
  • 13
  • I dont quite understand the `withDelay` part for when status is true but I guess it has something to do with the `Dots` and the `HealthContainer`? – PhantomSpooks Jan 03 '23 at 08:59
  • Hi, thanks for the clear answer. Yes WithDelay is here to display for 5sec the green status. The shared value is in fact what i need, i was not implemented it in the right way. Now it's ok but i still have the an issue when the app is loaded and opened by the user. The status green is shown while it must be shown only when it was precede with a red. Green must not be present on startup. I imagine all the component should render on startup especially with the useEffect once the app is loaded. – Raphaël Chemouni Jan 03 '23 at 20:01
  • Did you try giving status a default value of false? – PhantomSpooks Jan 03 '23 at 20:16
  • Yes, even with default state value on false, the the status is fetched from UseNetinfo on startup and set the state to true. – Raphaël Chemouni Jan 03 '23 at 22:11
  • I've tried with useRef to get the previous value and in the condition : prevState && !newStatus but without success – Raphaël Chemouni Jan 04 '23 at 00:05
  • Could you link what you have? – PhantomSpooks Jan 04 '23 at 03:50
  • Here's an older version where `animationDriver` is updated in a separate useEffect https://snack.expo.dev/b6id8s9DZ – PhantomSpooks Jan 04 '23 at 03:57
  • I've forgot to say that my component is called in the App navigation stack to put this modal on all the screens. Even with a separate use effect it run once on startup. I've nothing more for this component, just the app stack. i can share specific things if you need but i cant share all the or screens. – Raphaël Chemouni Jan 04 '23 at 16:24