facebook / react

The library for web and native user interfaces.
https://react.dev
MIT License
227.59k stars 46.43k forks source link

Bug: Strange behaviour of reactjs #22966

Closed ats1999 closed 2 years ago

ats1999 commented 2 years ago

React version: ^16.9.0

Steps To Reproduce

Consider the below UI.

image

You can see a heading, Logo Uploaded and Organisation logo

LogoComponent.jsx

import React, { useEffect, useState } from "react";
import { Card } from "reactstrap";
import UploadLogo from "./UploadLogo";
import axios from "axios";
import BASE_URL from "../../config/urls";
import DeleteIcon from "@material-ui/icons/Delete";
import { IconButton } from "@material-ui/core";
import { makeStyles } from "@material-ui/core/styles";
import UploadLogoOfOrg from "./UploadLogoOfOrg";

const useStyles = makeStyles((theme) => ({
  DeleteIcon: {
    fontSize: "15px",
    color: "black",
  },
}));

export default function OrgLogoCard({ orgId }) {
  const classes = useStyles();
  const [logos, setLogos] = useState([]);
  const [orgLogo, setOrgLogo] = useState("");

  useEffect(() => {
    axios
      .get(`${BASE_URL}client/get-logo-org?_id=${orgId}`, {
        headers: {
          "Content-Type": "multipart/form-data",
          "x-access-token": localStorage.getItem("vyoriusUserAuth"),
        },
      })
      .then((res) => setLogos(res.data))
      .catch((err) => {
        console.log(err);
      });

    axios
      .get(`${BASE_URL}client/get-logo-of-org?_id=${orgId}`, {
        headers: {
          "x-access-token": localStorage.getItem("vyoriusUserAuth"),
        },
      })
      .then((res) => setOrgLogo(res.data))
      .catch((err) => {
        console.log(err);
      });
  }, []);

  const addLogo = (logo) => {
    setLogos([...logos, logo]);
  };

  const deleteIcon = (logo) => {
    axios
      .post(
        `${BASE_URL}client/remove-logo-org`,
        {
          _id: orgId,
          logo,
        },
        {
          headers: {
            "x-access-token": localStorage.getItem("vyoriusUserAuth"),
          },
        }
      )
      .then((_) => {
        setLogos(logos.filter((l) => l != logo));
      })
      .catch((err) => {
        console.log(err, err?.response?.data);
        alert("Can not remove logo at the moment!");
      });
  };
  return (
    <Card className="m-2 p-2 border-0">
      <div className="d-flex">
        <h6 className="mr-2 ml-2">Logo Uploaded</h6>{" "}
        <UploadLogo orgId={orgId} addLogo={addLogo} />
      </div>
      <div>{logos.length == 0 && "There is no logo!"}</div>
      <div className="d-flex p-2 flex-wrap">
        {logos.map((ele, index) => (
          <div key={index} className="position-relative">
            <img
              className="mr-1 mt-1"
              src={ele}
              alt=""
              style={{
                height: "40px",
                width: "80px",
              }}
            />

            <div
              style={{
                top: "-10px",
                right: "0px",
              }}
              className="position-absolute"
            >
              <IconButton
                onClick={() => deleteIcon(ele)}
                color="secondary"
                aria-label="delete"
                size="small"
              >
                <DeleteIcon className={classes.DeleteIcon} fontSize="inherit" />
              </IconButton>
            </div>
          </div>
        ))}
      </div>

      <div className="d-flex mt-4">
        <h6 className="mr-2 ml-2">Organization logo</h6>{" "}
        <UploadLogoOfOrg
          orgId={orgId}
          addLogo={(loc) => setOrgLogo(loc)}
        />
      </div>

      <div className="d-flex">
        <img
          className="mr-1 mt-1"
          src={orgLogo}
          alt=""
          style={{
            height: "40px",
            width: "80px",
          }}
        />
      </div>
    </Card>
  );
}

UploadLogo.jsx

import React from "react";
import AddAPhotoIcon from "@material-ui/icons/AddAPhoto";
import axios from "axios";
import { BASE_URL } from "../../config/urls";
import { connect } from "react-redux";
import { makeStyles } from "@material-ui/core/styles";

const useStyles = makeStyles((theme) => ({
  AddAPhotoIcon: {
    height: "1rem",
    marginTop: "-10px",
    color: "black",
  },
}));

// isOrgLogo - logo of the org
function UploadOrgLogos({ userInfo, addLogo, orgId }) {
  const classes = useStyles();
  return (
    <form>
      <label
        htmlFor="file-input"
        style={{
          cursor: "pointer",
        }}
      >
        <AddAPhotoIcon className={classes.AddAPhotoIcon} color="primary" />
      </label>

      <input
        style={{
          display: "none",
        }}
        id="file-input"
        type="file"
        onChange={(e) => {
          if (!e.target.files[0]) return;
          // if there is no user
          // TODO: add toast  notification
          if (!userInfo || !userInfo.email) {
            console.log("User is not in redux!");
          }

          const role = userInfo.userRole.find(
            (role) => role.organization == orgId
          );
          if (!role || role.role != "SuperAdmin") {
            alert("Not a super admin!");
            return;
          } else {
            console.log("A super admin!");
          }
          let formData = new FormData();
          formData.append("file", e.target.files[0]);
          formData.append("folder", "org-logos");
          formData.append("fileId", "org-logo");
          formData.append("bucket", "vyoriusdronesdatabase");
          formData.append("_id", orgId);

          axios
            .post(`${BASE_URL}client/add-logo-org`, formData, {
              headers: {
                "Content-Type": "multipart/form-data",
                "x-access-token": localStorage.getItem("vyoriusUserAuth"),
              },
            })
            .then((res) => addLogo(res.data))
            .catch((err) => {
              console.log(err);
              alert("Error in uploading file...");
            });
        }}
      />
    </form>
  );
}

const mapStateToProps = ({ login_details }) => {
  return {
    userInfo: login_details.login_detail,
  };
};
// HMR
export default connect(mapStateToProps, null)(UploadOrgLogos);

UploadLogoOfOrg.jsx

import React from "react";
import AddAPhotoIcon from "@material-ui/icons/AddAPhoto";
import axios from "axios";
import { BASE_URL } from "../../config/urls";
import { connect } from "react-redux";
import { makeStyles } from "@material-ui/core/styles";

const useStyles = makeStyles((theme) => ({
  AddAPhotoIcon: {
    height: "1rem",
    marginTop: "-10px",
    color: "black",
  },
}));

function UploadOrgLogos({ userInfo, addLogo, orgId }) {
  const classes = useStyles();
  return (
    <form>
      <label
        htmlFor="file-input"
        style={{
          cursor: "pointer",
        }}
      >
        <AddAPhotoIcon className={classes.AddAPhotoIcon} color="primary" />
      </label>

      <input
        style={{
          display: "none",
        }}
        id="file-input"
        type="file"
        onChange={(e) => {
          if (!e.target.files[0]) return;

          // if there is no user
          // TODO: add toast  notification
          if (!userInfo || !userInfo.email) {
            console.log("User is not in redux!");
          }

          const role = userInfo.userRole.find(
            (role) => role.organization == orgId
          );
          if (!role || role.role != "SuperAdmin") {
            alert("Not a super admin!");
            return;
          } else {
            console.log("A super admin!");
          }
          let formData = new FormData();
          formData.append("file", e.target.files[0]);
          formData.append("folder", "org-logos");
          formData.append("fileId", "org-logo");
          formData.append("bucket", "vyoriusdronesdatabase");
          formData.append("_id", orgId);

          axios
            .post(`${BASE_URL}client/add-logo-of-org`, formData, {
              headers: {
                "Content-Type": "multipart/form-data",
                "x-access-token": localStorage.getItem("vyoriusUserAuth"),
              },
            })
            .then((res) => addLogo(res.data))
            .catch((err) => {
              console.log(err);
              alert("Error in uploading file...");
            });
        }}
      />
    </form>
  );
}

const mapStateToProps = ({ login_details }) => {
  return {
    userInfo: login_details.login_detail,
  };
};
// HMR
export default connect(mapStateToProps, null)(UploadOrgLogos);

Clicking on any one of them, the request is being sent to client/add-logo-org. If I remove <UploadLogo orgId={orgId} addLogo={addLogo} / from LogoComponent.jsx then its working fine.

Edited

If I swap <UploadLogoOfOrg orgId={orgId} addLogo={(loc) => setOrgLogo(loc)} /> with <UploadLogo orgId={orgId} addLogo={addLogo} /> then all request are being sent on /client/add-logo-of-org.

gaearon commented 2 years ago

Sorry, this is quite a bit of code and it's not runnable. If it's a usage question, please ask on StackOverflow. If you think it's a React bug, please provide a minimal and runnable reproducing case. Thanks.