Home > Software engineering >  how to do condition based don't repeat yourself (dry) principle in React JS?
how to do condition based don't repeat yourself (dry) principle in React JS?

Time:02-24

code output

way to use component:

  import React from "react";
  import MyAvatars from "../../components/MyAvatar/MyAvatars";

  const About = () => {
   return (
  
    <MyAvatars
      topType={[true, 1000]}
      accessoriesType={[true, 1200]}
      facialHairType={["blank"]}
    />
   );
 };

 export default About;

This is my code. I am currently working on this.

Code:

  import React from "react";
  import Avatar from "avataaars";
  import { Top, Accessories, FacialHair } from "./avatarThings";

  const MyAvatar = ({ topType, facialHairType }) => {
  
  const [avatar, setAvatar] = React.useState({
      avatarStyle: "Circle",
      topType: "ShortHairDreads01",
      accessoriesType: "Blank",
      facialHairType: "Blank",
});


const topFunc = () =>{
    if (topType.length === 2) {
      const interval = setInterval(() => {
        setAvatar((prev) => {
          return {
            ...prev,
            topType:  Top[Math.floor(Math.random() * Top.length)],
          };
        });
      }, topType[1]); //this is time
      return () => clearInterval(interval);
    }
    setAvatar((prev) => {
      return {
        ...prev,
        topType: topType[0],
      };
    });
}

const FacialHairFunc = () =>{
      if (facialHairType.length === 2) {
      const interval = setInterval(() => {
        setAvatar((prev) => {
          return {
            ...prev,
            facialHairType: FacialHair[Math.floor(Math.random() * FacialHair.length)],
          };
        });
      }, facialHairType[1]);
      return () => clearInterval(interval);
    }
    setAvatar((prev) => {
      return {
        ...prev,
        facialHairType: facialHairType[0],
      };
    });
}

React.useEffect(() => {

  if (topType) {
    topFunc()
  }
  if (facialHairType) {
    FacialHairFunc()
  }

}, [])


return (
  <Avatar
    avatarStyle="Circle"
    topType={avatar.topType}
    accessoriesType={avatar.accessoriesType}
    hairColor={avatar.hairColor}
    facialHairType={avatar.facialHairType}
  />

 );
};

export default MyAvatar;

I am new to programming. I am currently creating a useful open-source NPM Package.

This is the code for it. Repeat the same code over and over again.

I wish I could modify this code more easily than this, but I could not. It's very easy for people to admire you. And I'll learn new things with the code you write for this.

I would be very glad if you help.

Please help and let me know your contribution as well.

Thanks :)

CodePudding user response:

You've a bit of coupling between the functions to effectively compute a random attribute, and the aspect of updating the avatar state.

I suggest converting each "attribute" function that selects a random attribute and updates the state into a single React hook that takes an array of attributes and the interval, and returns the random attributes, and simply pass each randomly selected attribute directly to the Avatar component. There's not a compelling reason to have the intermediate avatar state in your component.

Example:

const getRandomAttribute = arr => arr[Math.floor(Math.random() * arr.length)];

const useRandomAttribute = (attributes = [], valueArr = []) => {
  const [attribute, setAttribute] = useState(() => {
    if (valueArr[0]) {
      return getRandomAttribute(attributes);
    }
  });

  useEffect(() => {
    let timerId;
    if (valueArr[0] && valueArr[1] > 0) {
      timerId = setInterval(() => {
        const attribute = getRandomAttribute(attributes);
        setAttribute(attribute);
      }, valueArr[1]);
    }
    return () => clearTimeout(timerId);
  }, [attributes, valueArr]);

  return attribute;
};

App

import React from "react";
import Avatar from "avataaars";
import { Top, Accessories, FacialHair, ..... } from "./avatarThings";

const MyAvatar = ({ topType, facialHairType, accessoriesType, hairType }) => {
  const accessory = useRandomAttribute(Accessories, accessoriesType);
  const face = useRandomAttribute(FacialHair, facialHairType);
  const hair = useRandomAttribute(Hair, hairType);
  const top = useRandomAttribute(Top, topType);

  return (
    <Avatar
      avatarStyle="Circle"
      topType={top || "ShortHairDreads01"}
      accessoriesType={accessory || "Blank"}
      hairColor={hair || "BrownDark"}
      facialHairType={face || "Blank"}
      clotheType="Hoodie"
      clotheColor="Red"
      eyeType="Wink"
      eyebrowType="Default"
      mouthType="Smile"
      skinColor="Brown"
    />
  );
};

You can tune the code from here for the interval timing, other default/fallback values, etc.

Edit how-to-do-condition-based-dont-repeat-yourself-dry-principle-in-react-js

CodePudding user response:

Do you can create just a function parsing the required args:

import React from "react";
import Avatar from "avataaars";
import { Top, Accessories, FacialHair } from "./avatarThings";

const MyAvatar = ({ topType, facialHairType }) => {

const [avatar, setAvatar] = React.useState({
    avatarStyle: "Circle",
    topType: "ShortHairDreads01",
    accessoriesType: "Blank",
    facialHairType: "Blank",
});

const typeFunction = (type, AvatarComponent) =>{
    if (type.length === 2) {
        const interval = setInterval(() => {
            setAvatar((prev) => {
                return {
                    ...prev,
                    type: AvatarComponent[Math.floor(Math.random() * AvatarComponent.length)],
                };
            });
        }, type[1]);
        return () => clearInterval(interval);
    }
    setAvatar((prev) => {
        return {
            ...prev,
            type: type[0],
        };
    });
}

React.useEffect(() => {
    if (topType) {
        typeFunction(type, Top)
    }
    if (facialHairType) {
        typeFunction(facialHairType, FacialHair)
    }
}, [])


return (
        <Avatar
            avatarStyle="Circle"
            topType={avatar.topType}
            accessoriesType={avatar.accessoriesType}
            hairColor={avatar.hairColor}
            facialHairType={avatar.facialHairType}
        />
    );
};

export default MyAvatar;
  • Related