При передаче изображения через useContext из входа в систему изображение не отображается

Во время onSubmit при входе в систему я сделал setLoginPhoto(res.data.photo), а затем использовал useContext(), чтобы передать информацию о фотографии в Navigation. Но, по-видимому, информация о фотографии очищается после успешного входа в систему и отображения главного экрана. Также loginPhoto.photo, только фото undefined, но я могу видеть детали изображения в loginPhoto при наведении на него курсора.

При нажатии «Войти» я установил различные точки останова и увидел, что информация об изображении фактически передается в UserLoginProvider, а затем становится доступной в Navigation. (см. скриншоты)

Примечание. Путь к файлу изображения сохраняется в базе данных с помощью мультиплексора, т. е. [ 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
Спасибо itsanewabstract, очень впечатляющий и хороший ответ. Теперь это работает, но я заметил проблему, если я обновляю браузер, теперь изображение исчезает. - 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
Спасибо, itsanewabstract. Что касается вопроса, я хотел бы получить данные из столбцов 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
У меня есть еще одна проблема с массивом реагирующих крючков, не могли бы вы взглянуть, если у вас есть время: -are-not-completely-displaying-in-react-ho" title="при повторении массива записи не полностью отображаются в react ho"> stackoverflow.com/questions/62586105/ - person soccerway; 26.06.2020