React Context, useReducer и Cloudinary для создания постоянства при refre sh браузера - PullRequest
0 голосов
/ 20 июня 2020

У меня есть Provider для размещения некоторых изображений и других данных для вошедшего в систему / авторизованного пользователя.

import React, { useState, useEffect, useReducer } from 'react';

var reducer = (userInfo, newUserInfo) => {
  return { ...userInfo, ...newUserInfo };
};

var initialState = {
  userId: null,
  avatar: '/static/uploads/profile-avatars/placeholder.jpg'
};

var UserContext = React.createContext();

function UserProvider({ children }) {
  var [userImages, setUserImages] = useReducer(reducer, initialState);

  var [userId, setUserId] = useState(userImages.userId);

  useEffect(() => {
    if (userId === null) {
      return setUserImages(userImages => ({
        ...userImages,
        initialState
      }));
    } else {
      axios
        .get(`/users/user_avatar`)
        .then(response => {
          console.log('response ', response);

          if (response.status === 200) {
            setUserImages(userImages => ({
              ...userImages,
              avatar: response.data.avatar_url
            }));
          }
        })
        .catch(function(error) {
          console.log(error);
        });
    }
  }, [initialState]);

  return (
    <UserContext.Provider
      value={{
        userImages,
        setUserImages,
        userId,
        setUserId
      }}
    >
      {children}
    </UserContext.Provider>
  );
}

export default UserContext;

export { UserProvider };

Когда пользователь входит в систему (я использую паспорт для авторизации), я отправляю userId я получаю от успешного входа / ответа, чтобы сохранить на клиенте, чтобы использовать позже для Cloudinary для их public_id, чтобы отслеживать avatar.

axios вызов в моем UserContext вызывает маршрут на моем express сервере, который проверяет Cloudinary и возвращает ответ для использования клиентом в ImageLoader ниже:

router.get('/user_avatar', (req, res) => {
  try {
    cloudinary.api.resources({ public_ids: [req.user._id] }, function(error, result) {
      res.json({
        avatar_url: result.secure_url
      });
    });
  } catch (error) {
    console.log(error);
  }
});

Это компонент ImageLoader :

import { useContext, useState } from 'react';
import {
  fetchPhotos,
  openUploadWidget
} from '../CloudinaryService/CloudinaryService.jsx';

import { Card, Icon, Image, Segment, Form } from 'semantic-ui-react';
import UserContext from '../UserContext/UserContext.jsx';

function ImageUploader() {
  const { userId, userImages, setUserImages } = useContext(UserContext);
  const { avatar } = userImages;

  function avatarUpdater(avatarPath) {
    setUserImages({ avatar: avatarPath, userId: userId });
  }

  console.log('userId ', userId);

  const beginUpload = tag => {
    const uploadOptions = {
      cloudName: 'hillfinders',
      context: `userId=${tag}`,
      publicId: tag,
      uploadPreset: 'upload'
    };

    openUploadWidget(uploadOptions, (error, photos) => {
      if (!error) {
        if (photos.event === 'success') {
          avatarUpdater(photos.info.secure_url);
        }
      } else {
        console.log(error);
      }
    });
  };

  return (
    <>
      <Segment>
        <Card fluid>
          <Image src={avatar} />
            <button onClick={() => beginUpload(userId)}>Upload Image</button>
        </Card>
      </Segment>
    </>
  );
}

export default ImageUploader;

Он использует useContext для установки аватара, который работает (загрузка, выход из системы, изображение все еще присутствует, когда я вхожу в систему), но как я могу сохранить изображение, если по какой-то причине браузер обновился?

...