0

My code is displaying the output twice for some reason and I cannot figure it out. Any help would be appreciated. this is the output that i am getting now . I believe it is something to do with setting setImagesCount. I tried transposing this from a class component to functional component, so I am not sure if i did it all correctly. i would like to sort them by id, but I am not able to figure out how to do it. in addition, is there a way to set up a custom search/map parameter, such as the wallet address to get their posts.

import Decentragram from "../build/contracts/Decentragram.json";
import Web3 from "web3";
import { useState, useEffect } from "react";

const Home = () => {
  const ipfsClient = require("ipfs-http-client");
  const ipfs = ipfsClient({
    host: "ipfs.infura.io",
    port: 5001,
    protocol: "https",
  });

  const [account, setAccount] = useState("");
  const [decentragram, setDecentragram] = useState(null);
  const [images, setImages] = useState([]);
  const [loading, setLoading] = useState(true);
  const [imagesCount, setImagesCount] = useState(0);
  const [buffer, setBuffer] = useState(null);

  useEffect(() => {
    loadWeb3();
    loadBlockchainData();
  }, []);

  const loadWeb3 = async () => {
    if (window.ethereum) {
      window.web3 = new Web3(window.ethereum);
      await window.ethereum.request({ method: "eth_requestAccounts" });
    } else if (window.web3) {
      window.web3 = new Web3(window.web3.currentProvider);
    } else {
      window.alert(
        "Non-Ethereum browser detected. You should consider trying MetaMask!"
      );
    }
  };

  const loadBlockchainData = async () => {
    const web3 = window.web3;
    const accounts = await web3.eth.getAccounts();
    setAccount(accounts[0]);
    const networkId = await web3.eth.net.getId();
    const networkData = Decentragram.networks[networkId];
    if (networkData) {
      const decentragram = new web3.eth.Contract(
        Decentragram.abi,
        networkData.address
      );
      setDecentragram(decentragram);
      const imagesCount = await decentragram.methods.imageCount().call();
      setImagesCount(imagesCount);
      for (let i = 1; i <= imagesCount; i++) {
        const image = await decentragram.methods.images(i).call();
        setImages((prevImages) => [...prevImages, image]);
      }
      setImagesCount(imagesCount);
      setLoading(false);
    } else {
      window.alert("Smart contract not deployed to detected network.");
    }
  };

  const captureFile = async (event) => {
    event.preventDefault();
    const file = event.target.files[0];
    const reader = new window.FileReader();
    reader.readAsArrayBuffer(file);
    reader.onloadend = () => {
      setBuffer(Buffer(reader.result));
    };
  };

  const uploadImage = async (description) => {
    console.log("Submitting file to ipfs...");

    ipfs.add(buffer, (error, result) => {
      console.log("File was stored at Hash:", result);
      if (error) {
        console.error(error);
        return;
      }
      setLoading(true);
      decentragram.methods
        .uploadImage(result[0].hash, description)
        .send({ from: account })
        .on("transactionHash", (hash) => {
          setLoading(false);
        });
    });
  };

  return (
    <div>
      

      <form
        onSubmit={(event) => {
          event.preventDefault();
          const description = document.getElementById("imageDescription").value;
          uploadImage(description);
        }}
      >
        <input
          type="file"
          accept=".jpg, .jpeg, .png, .bmp, .gif"
          onChange={captureFile}
        />
        <input
          id="imageDescription"
          type="text"
          placeholder="Image description..."
          
          required
        />
        <button type="submit" class="btn btn-primary btn-block btn-lg">
          Upload!
        </button>
      </form>

      {images.map((image, key) => {
        return (
          <div key={key}>
            <img src={image.hash} alt={image.description} />
            <p>{image.description}</p>
          </div>
        );
      })}
    </div>
  );
};

export default Home;

1 Answers1

1

your code is not returing the mapped values twice, what you are seeing is the alt={image.description} values inside your <img /> tag, the alt values appear when the src={image.hash} is failing to load an image. When the image is loaded, you won't see this alt tag unless you pause the mouse pointer on the image.

make sure that your src={image.hash} is valid and your issue will be solved.

Omar Dieh
  • 500
  • 3
  • 8