TransWikia.com

How to render an element within a function in React?

Stack Overflow Asked by Peppa Box on January 28, 2021

I would like to render the return from the else if statement.

Is there a way to have the images render within the tags?

I would like to show a different image depending on the result returned from the API


export default function GetDieResult() {
  const [dieRollResult, setDieRollResult] = useState(1);
  
  const whichDieImageToDisply = (rollResult ) => {
    if (rollResult === 1) {
      return <img className="die" src={d1} alt="A die displaying 1" />;
    } else if (rollResult === 2) {
      return <img className="die" src={d2} alt="A die displaying 2" />;
    } else if (rollResult === 3) {
      return <img className="die" src={d3} alt="A die displaying 3" />;
    } else if (rollResult === 4) {
      return <img className="die" src={d4} alt="A die displaying 4" />;
    } else if (rollResult === 5) {
      return <img className="die" src={d5} alt="A die displaying 5" />;
    } else if (rollResult === 6) {
      return <img className="die" src={d6} alt="A die displaying 6" />;
    }
  };

  const checkResponse = (response) => {
    if (!response.ok) throw new Error(`Network error: ${response.status}`);
    return response.json();
  };

  const rollDie = () => {
    fetch("https://rolz.org/api/?d6.json")
      .then(checkResponse)
      .then((data) => {
        setDieRollResult(data.result);
        whichDieImageToDisply();
        console.log(whichDieImageToDisply(data.result))
      });
  };

  useEffect(() => {
    rollDie();
  }, [dieRollResult]);

  console.log(dieRollResult);

  return (
    <main>
    
      <img src={d1} alt="A die displaying 1" className="die" />
    </main>
  );
}


3 Answers

If I were you, I would do some refactoring on the code and simplify it a bit.

First, I would move the fetching to the useEffect hook and make the dependency array empty. This way it will only make the request to the API once after rendering the component. Then, I would create a status state so I can easier track in which status the component is currently at. This then allows me to render the correct image based on the dieRollResult that got fetched from the API. Also, you can simply call the dieImage() function in the JSX that will then render the correct image based on dieRollResult and because we are using status here, the dieImage() function will be called only when you have fetched the data from the API. Until then, it will show you a loading text.

function GetDieResult() {
  const [dieRollResult, setDieRollResult] = useState(1);
  const [status, setStatus] = useState("idle");

  const dieImage = () => {
    if (dieRollResult === 1) {
      return <img className="die" src={d1} alt="A die displaying 1" />;
    } else if (dieRollResult === 2) {
      return <img className="die" src={d2} alt="A die displaying 2" />;
    } else if (dieRollResult === 3) {
      return <img className="die" src={d3} alt="A die displaying 3" />;
    } else if (dieRollResult === 4) {
      return <img className="die" src={d4} alt="A die displaying 4" />;
    } else if (dieRollResult === 5) {
      return <img className="die" src={d5} alt="A die displaying 5" />;
    } else if (dieRollResult === 6) {
      return <img className="die" src={d6} alt="A die displaying 6" />;
    }
  };

  useEffect(() => {
    setStatus("fetching");

    fetch("https://rolz.org/api/?d6.json").then(async (res) => {
      if (!res.ok) {
        setStatus("failed");

        throw new Error(`Network error: ${res.status}`);
      }

      const { result } = await res.json();

      setDieRollResult(result);
      setStatus("processed");
    });
  }, []);

  return (
    <main>
      {status === "processed" ? (
        dieImage()
      ) : (
        <p style={{ color: "blue" }}>loading...</p>
      )}
    </main>
  );
}

Correct answer by Mantas Astra on January 28, 2021

import React from "react";

export default function Img (props) {

  const [myPic, setMyPic] = React.useState("");

  React.useEffect(() => {
    fetch(props.url)
      .then(res=>res.blob())
      .then(pic =>{
         const auxUrl = URL.createObjectURL(pic);
         setMyPic(auxUrl);

         return function () {
            URL.revokeObjectURL(auxUrl);
         }
      })
  }, [props.url]);

  return (
    <img src={myPic} />
  )
}

Answered by Ernesto on January 28, 2021

You can call function from return block. whichDieImageToDisply() .But if that function needs to take state, or needs to be defined inside component, and every render will create function again. You might need to wrap it with useCallback etc; but i will provide an alternative way, i think better and cleaner way, via enums.

Inside your return block you can use this; you wont need a whichDieImageToDisply function.

  {
    {
      1: <img className="die" src={d1} alt="A die displaying 1" />;,
      2: <img className="die" src={d2} alt="A die displaying 2" />,
      3: <img className="die" src={d3} alt="A die displaying 3" />,
      4: <img className="die" src={d4} alt="A die displaying 4" />;,
      5: <img className="die" src={d5} alt="A die displaying 5" />,
      6: <img className="die" src={d6} alt="A die displaying 6" />,
    }[dieRollResult]
  }

More: https://www.robinwieruch.de/conditional-rendering-react

Answered by Emre A on January 28, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP