Home > Software design >  React Native Changing the State is not re rendering component
React Native Changing the State is not re rendering component

Time:10-24

i am trying to use the isEnabled and setIsEnabled useState Hook to update the icon of the play button. When I hit the playbutton, the icon changes appropriately with the useState Hook assumingly triggering a re render, but hitting the restart btn (although i am calling the setIsEnabled) is not triggering a re render of the playbutton icon. Is there a way to force reload it or is there something I'm doing wrong with the useState hook

---- ActionBtn.jsx ------

    export const ActionButton = (props: {
      name: string;
      themeColor: string;
      timerReference: any;
    }) => {
      // tracker for whether timer is active
      const [isEnabled, setIsEnabled] = useState(false);
      // handle button press for each button
      // settings btn
      const openSettings = () => {
        addHapticFeedback("light");
        alert("settings");
      };
      // play & pause btn
      const toggleTimer = () => {
        // toggle play or pause button
        setIsEnabled(!isEnabled);
        addHapticFeedback("light");
        if (isEnabled) {
          props.timerReference.current.pause();
        } else {
          props.timerReference.current.play();
        }
      };
      // restart btn
      const restartTimer = () => {
        // deactivate timer
        setIsEnabled(false);
        addHapticFeedback("light");
        props.timerReference.current.reAnimate();
        props.timerReference.current.pause();
      };
    
      // define type of action button based on prop passed
      if (props.name === "settings") {
        return (
          <TouchableOpacity
            style={[styles.button, { backgroundColor: props.themeColor }]}
            onPress={openSettings}
          >
            <SettingsIcon size={iconSize} fillColor={iconColor} />
          </TouchableOpacity>
        );
      } else if (props.name === "play") {
        return (
          <TouchableOpacity
            style={[styles.button, { backgroundColor: props.themeColor }]}
            onPress={toggleTimer}
          >
            <PlayIcon size={iconSize} fillColor={iconColor} isEnabled={isEnabled} />
          </TouchableOpacity>
        );
      } else if (props.name === "restart") {
        return (
          <TouchableOpacity
            style={[styles.button, { backgroundColor: props.themeColor }]}
            onPress={restartTimer}
          >
            <RestartIcon size={iconSize} fillColor={iconColor} />
          </TouchableOpacity>
        );
      } else {
        return <View />;
      }
    };

----- ICONS.jsx ------



    export const PlayIcon = (props: {
      size: number;
      fillColor: string;
      isEnabled: boolean;
    }) => {
      return props.isEnabled ? (
        <Svg width={props.size} height={props.size} viewBox="0 0 40 40">
          <Path
            d="M25 31.6666C24.0833 31.6666 23.2989 31.3405 22.6467 30.6883C21.9933 30.035 21.6667 29.25 21.6667 28.3333V11.6666C21.6667 10.75 21.9933 9.96553 22.6467 9.31331C23.2989 8.65998 24.0833 8.33331 25 8.33331H28.3333C29.25 8.33331 30.035 8.65998 30.6883 9.31331C31.3406 9.96553 31.6667 10.75 31.6667 11.6666V28.3333C31.6667 29.25 31.3406 30.035 30.6883 30.6883C30.035 31.3405 29.25 31.6666 28.3333 31.6666H25ZM11.6667 31.6666C10.75 31.6666 9.96555 31.3405 9.31333 30.6883C8.65999 30.035 8.33333 29.25 8.33333 28.3333V11.6666C8.33333 10.75 8.65999 9.96553 9.31333 9.31331C9.96555 8.65998 10.75 8.33331 11.6667 8.33331H15C15.9167 8.33331 16.7017 8.65998 17.355 9.31331C18.0072 9.96553 18.3333 10.75 18.3333 11.6666V28.3333C18.3333 29.25 18.0072 30.035 17.355 30.6883C16.7017 31.3405 15.9167 31.6666 15 31.6666H11.6667Z"
            fill={props.fillColor}
          />
        </Svg>
      ) : (
        <Svg width={props.size} height={props.size} viewBox="0 0 55 55">
          <Path
            d="M21.84 41.277c-.762.495-1.534.523-2.316.084-.78-.437-1.17-1.113-1.17-2.028V15.667c0-.915.39-1.592 1.17-2.03.782-.438 1.554-.41 2.317.086l18.635 11.833c.686.458 1.03 1.106 1.03 1.944 0 .838-.344 1.486-1.03 1.944L21.841 41.277Z"
            fill={props.fillColor}
          />
        </Svg>
      );
    };
    
    export const RestartIcon = (props: { size: number; fillColor: string }) => {
      return (
        <Svg width={props.size} height={props.size} viewBox="0 0 46 46">
          <Path
            d="M24.875 22.25L29.5625 26.9375C29.9062 27.2812 30.0781 27.7187 30.0781 28.25C30.0781 28.7812 29.9062 29.2187 29.5625 29.5625C29.2188 29.9062 28.7812 30.0781 28.25 30.0781C27.7188 30.0781 27.2812 29.9062 26.9375 29.5625L21.6875 24.3125C21.5 24.125 21.3594 23.9137 21.2656 23.6787C21.1719 23.445 21.125 23.2031 21.125 22.9531V15.5C21.125 14.9687 21.305 14.5231 21.665 14.1631C22.0238 13.8044 22.4688 13.625 23 13.625C23.5312 13.625 23.9769 13.8044 24.3369 14.1631C24.6956 14.5231 24.875 14.9687 24.875 15.5V22.25ZM23 39.875C19.2188 39.875 15.8281 38.7575 12.8281 36.5225C9.82812 34.2887 7.8125 31.375 6.78125 27.7812C6.625 27.2187 6.68 26.6875 6.94625 26.1875C7.21125 25.6875 7.625 25.375 8.1875 25.25C8.71875 25.125 9.19562 25.2419 9.61812 25.6006C10.0394 25.9606 10.3281 26.4062 10.4844 26.9375C11.2969 29.6875 12.8675 31.9062 15.1962 33.5937C17.5237 35.2812 20.125 36.125 23 36.125C26.6562 36.125 29.7575 34.8512 32.3037 32.3037C34.8512 29.7575 36.125 26.6562 36.125 23C36.125 19.3437 34.8512 16.2419 32.3037 13.6944C29.7575 11.1481 26.6562 9.875 23 9.875C20.8438 9.875 18.8281 10.375 16.9531 11.375C15.0781 12.375 13.5 13.75 12.2188 15.5H15.5C16.0312 15.5 16.4769 15.6794 16.8369 16.0381C17.1956 16.3981 17.375 16.8437 17.375 17.375C17.375 17.9062 17.1956 18.3512 16.8369 18.71C16.4769 19.07 16.0312 19.25 15.5 19.25H8C7.46875 19.25 7.02375 19.07 6.665 18.71C6.305 18.3512 6.125 17.9062 6.125 17.375V9.875C6.125 9.34375 6.305 8.89812 6.665 8.53813C7.02375 8.17938 7.46875 8 8 8C8.53125 8 8.97687 8.17938 9.33687 8.53813C9.69562 8.89812 9.875 9.34375 9.875 9.875V12.4062C11.4688 10.4062 13.4144 8.85937 15.7119 7.76562C18.0081 6.67187 20.4375 6.125 23 6.125C25.3438 6.125 27.5394 6.57 29.5869 7.46C31.6331 8.35125 33.4144 9.55437 34.9306 11.0694C36.4456 12.5856 37.6488 14.3669 38.54 16.4131C39.43 18.4606 39.875 20.6562 39.875 23C39.875 25.3437 39.43 27.5387 38.54 29.585C37.6488 31.6325 36.4456 33.4137 34.9306 34.9287C33.4144 36.445 31.6331 37.6487 29.5869 38.54C27.5394 39.43 25.3438 39.875 23 39.875Z"
            fill={props.fillColor}
          />
        </Svg>
      );
    };



CodePudding user response:

You need to use useEffect hook with the restart function. See react docs for details.

code snippet:

import { useEffect } from 'react';

const _isEnabled = false;

  useEffect(() => {
    setIsEnabled(!_isEnabled);
  },[_isEnabled]);

Note: include useEffect hook right after your useState hook at top level. Update value of _isEnabled= !_isEnabled where you want to rerender and don't call setIsEnabled in that function.

CodePudding user response:

I managed to solve it by moving the isEnabled state variable to the parent object and then passing it down to the children

  • Related