ขณะส่งรูปภาพผ่าน useContext จากการเข้าสู่ระบบและรูปภาพไม่แสดง

ระหว่าง onSubmit ในการเข้าสู่ระบบ ฉันได้ setLoginPhoto(res.data.photo)แล้วใช้ useContext() เพื่อส่งข้อมูลภาพถ่ายไปยังการนำทาง แต่เห็นได้ชัดว่าข้อมูลรูปภาพกำลังถูกล้างออกไปเมื่อเข้าสู่ระบบสำเร็จและแสดงหน้าจอหลัก นอกจากนี้loginPhoto.photo รูปภาพเพียงอย่างเดียวคือ undefined แต่ฉันสามารถดูรายละเอียดรูปภาพใน loginPhoto ขณะที่วางเมาส์เหนือรูปภาพนั้น

เมื่อคลิกที่เข้าสู่ระบบ ฉันได้ตั้งค่าจุดพักต่างๆ และเห็นว่าข้อมูลรูปภาพถูกส่งไปที่ UserLoginProvider แล้วจึงพร้อมใช้งานใน Navigation (โปรดดูภาพหน้าจอ)

หมายเหตุ: เส้นทางไฟล์ภาพที่บันทึกลงในฐานข้อมูลโดยใช้ multer เช่น [ var imagePath = req.file.path;] และรูปภาพกำลังแสดงในหน้าจออื่น เช่น หน้าจอหลัก หน้าจอโปรไฟล์

ทีละขั้นตอน: กดที่เข้าสู่ระบบ ฉันจะเห็นว่ามีรูปภาพ loginPhoto ใน UserLoginProvider ( โปรดดูภาพหน้าจอ )

ป้อนคำอธิบายรูปภาพที่นี่

ตอนนี้ฉันเห็น loginPhoto พร้อมใช้งานในการนำทางแล้ว:

ป้อนคำอธิบายรูปภาพที่นี่

แต่เมื่อเข้าสู่ระบบสำเร็จและหน้าแรกปรากฏขึ้น loginPhoto จะกลายเป็นโมฆะและรูปภาพไม่แสดงในการนำทาง มีคำแนะนำเกี่ยวกับวิธีการแก้ไขปัญหานี้หรือไม่?

Login.js

import React, { useContext, useEffect, useState } from "react";
import { UserProfileContext, UserLoginContext } from '../context';

  const {loginPhoto, setLoginPhoto} = useContext(UserLoginContext);
  const [helperText, setHelperText] = useState('');
  const [value, setValue] = React.useState('');
const onSubmit = () => {
    const fetchData = async () => {
      try {
        const res = await axios.post('http://localhost:8000/service/login', { email, password });
        //setLoginData(res.data.loginData);  
        console.log("Front End success message:" + res.data.success);
        console.log("My Photo Data:" + res.data.photo);
        setLoginPhoto(res.data.photo);
        if (res.data.success) {
          setHelperText("Login successfully");
          setValue(res.data.privilege);
          localStorage.setItem('Privilege', res.data.privilege);
          localStorage.setItem('loginEmail', email);
          history.push('/')
          window.location.reload(true)
        }
        else {
          const failMessage = res.data.fail;
          setHelperText(failMessage);
        }
      } catch (e) {
        console.log(e.response.data);
        setHelperText(e.response.data.fail);
      }
    }
    fetchData();
  };

UserLoginProvider.js

import { UserProfileContext, UserLoginContext } from '../context';

const UserLoginProvider = ({children}) => {

    const [loginPhoto, setLoginPhoto] = useState({ photo: ''});

    console.log("Nav Image:"+loginPhoto);

     const value = useMemo(() => ({
        loginPhoto, setLoginPhoto
    }), [loginPhoto]);

    return (
       <UserLoginContext.Provider value={value}>
           {children}
       </UserLoginContext.Provider>
    )   
}
export default UserLoginProvider;

Navigation.js

import { UserProfileContext, UserLoginContext } from '../context';
    const { loginPhoto } = useContext(UserLoginContext);
    
        useEffect(() => {
            if (loginPhoto.photo) {
            
            const reader = new FileReader();
            reader.addEventListener('load', () => {
                setImgSrc(reader.result);
                localStorage.setItem("imgData", reader.result);
            });
            reader.readAsDataURL(loginPhoto.photo);
            }
        }, [loginPhoto.photo])
    
        var loginUserImg = localStorage.getItem('imgData');
    
        console.log(loginUserImg);
    
     <img className="nav_profile" src={loginUserImg}></img>

App.js

var ReactDOM = require("react-dom");


const App = () => {

  return (
  <BrowserRouter>
  <UserLoginProvider>
    <UserProfileProvider>
          <>
        <Navigation />
          <Switch>
              <ProtectedRoute exact path="/" component={Home} />
              <ProtectedRoute path="/profile" component={Profile} />
              <ProtectedRoute path="/aboutus" component={Aboutus} />
              <ProtectedRoute path="/availability" component={Availability} />
              <Route path="/register" component={Register} />
              <Route path="/login" component={Login} />
              <Route exact path="*" component={ErrorPage} />
          </Switch>
          </>
      </UserProfileProvider>
    </UserLoginProvider>
   </BrowserRouter>
  );
};
ReactDOM.render(
  React.createElement(App, null),
  document.getElementById("root")
);

export default App;

home.js

import React, { useRef, useEffect, useState } from "react";
import AlertDialog from "../modal/Dialog";
import Axios from "axios";


const Home = () => {

  const [phoneTooltip, setPhoneTooltip] = useState({ show: false, position: "absolute" });
  const [playerList, setPlayerList] = useState([]);
  const [searchTerm, setSearchTerm] = useState("");
  const [searchResults, setSearchResults] = useState([]);
  const [deleteIcon, setDeleteIcon] = useState({ show: false });
  const [deleteDialog, setDeleteDialog] = useState(false);
  const [playerId, setPlayerId] = useState("");
  const isMounted = useRef(false);
  const [isLoading, setIsLoading] = useState(true);


  const handleChange = event => {
    setSearchTerm(event.target.value);
  };


  useEffect(() => {
    isMounted.current = true;
    return () => isMounted.current = false;
  }, []);


  useEffect(() => {
    setTimeout ( () => {
    const fetchData = async () => {
      try {
        const res = await Axios.get('http://localhost:8000/service/players');
        if (isMounted.current) {
          setPlayerList(res.data.players);
          setSearchResults(res.data.players);
          const privilege = localStorage.getItem('Privilege');
          console.log("What is getting in Front End:" + privilege);
          showDeleteIcon(privilege);
          setIsLoading(false);
        }
      } catch (e) {
        if (isMounted.current) {
          setIsLoading(false);
        }
        console.log(e);
      }
    }
    fetchData();
    }, 1500);
  }, []);


  useEffect(() => {
    const results = playerList.filter(player =>
      player.name.toLowerCase().includes(searchTerm) || player.name.toUpperCase().includes(searchTerm) || player.position.toLowerCase().includes(searchTerm)
      || player.position.toUpperCase().includes(searchTerm)
    );
    setSearchResults(results);
  }, [searchTerm, playerList]);


  const displayPhoneToolTip = (userId) => e => {
    e.preventDefault();
    setPhoneTooltip(userId); // show tooltip
    setTimeout(() => {
      setPhoneTooltip(false); // remove/hide tooltip
    }, 4000);
  };

  const showDeleteIcon = (privilege) => {
    if (privilege === "ADMIN") {
      setDeleteIcon({ show: true })
    } else {
      setDeleteIcon({ show: false })
    }
  }
  const deletePlayer = (id) => e => {
    setPlayerId(id);
    setDeleteDialog(true);
  }

  const onDelete = id => () => {
    try {
      Axios.delete('http://localhost:8000/service/player', {
        headers: {
          'Content-Type': 'application/json'
        },
        data: {
          'id': id
        }
      });
      setDeleteDialog(false);
      const restOfPlayerResults = searchResults.filter((result) => result.id !== id)
      setSearchResults(restOfPlayerResults);
    } catch (e) {
      console.log(e);
    }
  }


  return (
    <div className="App">
      <div className="wrapper">
        <div className="playerList_header">
          <h2>Players</h2>
          <label>
            <div className="playerSearch_Home">
              <div className="playerSearch_Icon">
                <img alt="" src="/images/search-image-player.jpg"></img>
              </div>
              <input type="text" className="playerSearch_Home_Input" placeholder="Search players..." value={searchTerm} onChange={handleChange} />
            </div>
          </label>
        </div>
        <div>
        {!searchResults.length && !isLoading && (<div> <p className="noSearchData"> Does not match any results! </p> </div>)}
        <div className="playerList_home_page">
        {isLoading ? (
        <div className="loader">
        <div className="bubble"></div>
        <div className="bubble"></div>
        <div className="bubble"></div>
        <div className="bubble"></div>
      </div>
      ) : (
          <div className="grid-container">
            {
              searchResults.map(({ id, photo, position, phonenumber, name }) => (
                <div key={id} className="grid-item">
                  {
                    deleteIcon.show && (
                      <span className="deletePlayerButton" onClick={deletePlayer(id)}>
                        <img className="deletePlayerimg" src="/images/delete.png"></img>
                      </span>
                    )}
                  <div>
                    <img alt="" className="playerProfilePic_home_tile" key={photo} src={photo}></img>
                  </div>
                  <div className="playerProfile_grid_border">
                    <span className="rec_name_position_data">
                      <h3 key={name}>{name}</h3>
                      <span className="playerPosition_home_tile" key={position}>{position}</span>
                    </span>
                  </div>
                  <span className="phoneNumber_home">
                    <img src="/images/phone.png" alt={"phoneTooltip.show"} key={id} name="phoneNumberhomeicon" onClick={displayPhoneToolTip(id)} />
                  </span>
                  {phoneTooltip === id && (
                    <div className="tooltip_PhoneNumber_home" key={phonenumber}>{phonenumber}</div>
                  )}
                </div>
              ))
            }
          </div>
         )}
        </div>
       </div> 
      </div>
      <AlertDialog
        onDelete={onDelete}
        open={deleteDialog}
        onClose={() => setDeleteDialog(false)}
        playerId={playerId}
      />
    </div>
  );
}

export default Home;

person soccerway    schedule 19.06.2020    source แหล่งที่มา
comment
เฮ้ ฉันไม่มีโอกาสดูทุกสิ่งใน Codesandbox แต่จากสิ่งที่ฉันเห็นเพียงแค่ดูคร่าวๆ ก็คือคุณกำลังพยายามเข้าถึงคุณสมบัติ photo บน loginPhoto แต่ใน Login.js คุณตั้งค่าบริบท loginPhoto เป็นสตริงด้วย setLoginPhoto(res.data.photo) ดังนั้นคุณสมบัตินี้จึงไม่มีอยู่จริง ดังนั้นเหตุใดดีบักเกอร์ของคุณจึงแสดงสตริงรูปภาพที่ถูกต้องเมื่อโฮเวอร์ แจ้งให้เราทราบหากนี่คือสาเหตุของข้อผิดพลาด   -  person itsanewabstract    schedule 23.06.2020
comment
ฉันคิดว่าอย่างที่คุณบอกว่าฉันสามารถดูสตริงในการเข้าสู่ระบบได้ที่นี่ setLoginPhoto(res.data.photo) ทันทีที่เข้าสู่ระบบสำเร็จและแสดงหน้าแรก เมื่อถึงจุดหนึ่งมันก็กลายเป็นโมฆะ...   -  person soccerway    schedule 23.06.2020
comment
ฉันหมายถึงเมื่อหน้าแรกปรากฏขึ้น ฉันไม่สามารถดูสตริงรูปภาพได้อีกต่อไป..   -  person soccerway    schedule 23.06.2020
comment
เมื่อฉันได้ภาพแล้ว จะต้องแปลงเป็น base64 เพื่อจัดเก็บไว้ใน LocalStorage ...เพื่อที่ฉันจะสามารถแสดงในการนำทางเป็น login user image/photo   -  person soccerway    schedule 23.06.2020
comment
อาจเป็นปัญหากับการรัน window.location.reload(true) ในฟังก์ชัน fetchData ของ Login.js หรือไม่ บางทีการโหลดซ้ำอาจทำให้ค่าในบริบทหายไป หากยังไม่สามารถแก้ไขได้ ให้โพสต์ลิงก์ไปยังแอปตัวเต็ม แล้วฉันจะตรวจสอบให้ละเอียดยิ่งขึ้น   -  person itsanewabstract    schedule 23.06.2020
comment
ฉันได้ลองแสดงความคิดเห็นในส่วนโหลดซ้ำ //window.location.reload(true) แล้ว   -  person soccerway    schedule 23.06.2020
comment
เมื่อฉันกำหนดจุดพัก ฉันสามารถเห็นภาพมาที่นี่ var loginUserImg = localStorage.getItem('imgData'); .แต่ในขณะที่ดำเนินการต่อไปยังจุดพัก รูปภาพจะไปที่บรรทัดนี้อีกครั้ง const { loginPhoto } = useContext(UserLoginContext);   -  person soccerway    schedule 23.06.2020
comment
ตอนนั้นมันเป็นโมฆะ..   -  person soccerway    schedule 23.06.2020
comment
พฤษภาคมทันทีที่เข้าสู่ระบบและแสดงหน้าแรก...   -  person soccerway    schedule 23.06.2020
comment
รหัสที่มาเต็ม? ส่วนประกอบเราเตอร์และส่วนประกอบโฮมเพจจะมีประโยชน์อย่างยิ่ง   -  person itsanewabstract    schedule 23.06.2020
comment
ฉันได้เพิ่ม App.js และส่วนประกอบ Home สำหรับการอ้างอิงของคุณแล้ว   -  person soccerway    schedule 23.06.2020


คำตอบ (1)


ฉันได้สร้างแอปเวอร์ชันตัวอย่างเล็กๆ น้อยๆ ที่แก้ไขปัญหาของคุณแล้ว จากสิ่งที่ฉันบอกได้ ปัญหาคือ loginPhoto ถูกส่งผ่านเป็นสตริง แทนที่จะเป็นออบเจ็กต์ในรูปแบบ {photo: "image/example.jpeg"}

ปัญหาอีกประการหนึ่งคือ window.location.reload(true) ถูกเรียกหลังจากกดไปที่หน้า Home สิ่งนี้ทำให้บริบทหมดไป

คุณสามารถไปที่ Codesandbox ของฉันเพื่อดูว่ามีอะไรบ้าง ฉันเปลี่ยนไป กรอกข้อมูลการเข้าสู่ระบบเพิ่มเติมของคุณภายในเชลล์นี้และดูว่าสิ่งต่าง ๆ ทำงานได้หรือไม่

person itsanewabstract    schedule 23.06.2020
comment
ขอบคุณ itanewabstract คำตอบที่น่าประทับใจและดีมาก ใช้งานได้แล้ว แต่ฉันสังเกตเห็นปัญหาหากรีเฟรชเบราว์เซอร์ รูปภาพจะหายไปในขณะนี้ - person soccerway; 24.06.2020
comment
มีวิธีใดบ้างที่เราสามารถแก้ไขภาพการรีเฟรชเบราว์เซอร์หายไปได้... - person soccerway; 24.06.2020
comment
@soccerway อ๋อ ใช่ นั่นเป็นการพิมพ์ผิดในส่วนของฉัน ฉันใช้ localStorage.setItem("imgData", loginPhoto.photo) ตอนที่ฉันควรตั้งค่า res.data.photo แทน ฉันแก้ไขโค้ดแล้วและรูปภาพควรจะคงอยู่ในขณะนี้ - person itsanewabstract; 24.06.2020
comment
เพื่อนที่ยอดเยี่ยม ขอขอบคุณทุกความช่วยเหลือของคุณ - person soccerway; 24.06.2020
comment
คุณมีความคิดบ้างไหมว่าเหตุใดการเชื่อมโยงโมเดลจึงไม่ทำงานในกรณีนี้ ฉันมีตารางง่ายๆ สองตาราง นั่นคือ ผู้ใช้ ความพร้อม แต่ฉันยังคงได้รับผู้ใช้ไม่เกี่ยวข้องกับความพร้อมใช้งาน: stackoverflow.com/questions/62525061/ - person soccerway; 25.06.2020
comment
@soccerway ฉันจะลองดูว่าฉันจะทำอะไรได้บ้าง - person itsanewabstract; 25.06.2020
comment
ขอบคุณ itanewabstract .. ตามคำถามฉันต้องการรับข้อมูลจาก photo , position คอลัมน์จากตารางผู้ใช้และ dailystatus คอลัมน์จากตารางความพร้อมใช้งาน มีการระบุโมเดลในคำถาม MySQL เป็นฐานข้อมูลของฉันและใช้เครื่องมือ dbeaver เพื่อเชื่อมต่อกับฐานข้อมูลและดูตาราง .. ฉันสร้างฐานข้อมูลแล้ว แต่ตารางจะถูกสร้างขึ้นโดยอัตโนมัติจากโมเดล Sequelize ในขณะที่เรียกใช้ไฟล์ server.js - person soccerway; 25.06.2020
comment
@soccerway ฉันดูคำถามแล้ว แต่ดูเหมือนว่าจะเป็นคำถาม SQL มากกว่าคำถาม React น่าเสียดายที่ฉันไม่คุ้นเคยกับ SQL มากนัก ดังนั้นฉันคิดว่าคำถามอยู่นอกเหนือความเชี่ยวชาญของฉัน แต่ถ้าคุณมีคำถามเฉพาะเจาะจงเกี่ยวกับ React เพิ่มเติม โปรดแจ้งให้เราทราบ - person itsanewabstract; 25.06.2020
comment
ฉันมีปัญหาอาร์เรย์ react-hooks อีกปัญหาหนึ่ง คุณช่วยดูหน่อยได้ไหมว่าคุณมีเวลา: stackoverflow.com/questions/62586105/ - person soccerway; 26.06.2020