Home > Software design >  How can I obtain an image link that is in the body of my GET request using React.js?
How can I obtain an image link that is in the body of my GET request using React.js?

Time:04-04

I am using a spring boot backend with a react.js frontend for a web application. Once a user is logged in, it directs the user to their Profile where they will have their username, profile picture, and a banner displayed on the screen. I have developed a backend service that returns the necessary information in the body of my GET request on Postman such as the link of the image (Profile or Banner). How can I use React to obtain the necessary link in profile_img_complete and insert it into my image that has a default image in it already if the value is null? My demo user has an image in the database ready to be used, so it should not be displaying the default image, but it is. Any help would be deeply appreciated, here is an image of the information on Postman. enter image description here

Profile.jsx:

import React, {useState, useEffect} from 'react';
import {Link} from 'react-router-dom';
import {useSelector} from 'react-redux';
import UserProfileService from '../../services/user-profile.service';
import './styles/Profile.css';
const Profile = () => {
    const {user: currentUser} = useSelector((state) => state.auth);
    const {id: currentId} = useSelector((state) => state.auth);
    const [content, setContent] = useState('');
    const [photoURL, setPhotoURL] = useState('../../images/user-solid.svg');
 //user-solid is the default image I want if the profile image link is null
    useEffect(() => {
        UserProfileService.getProfile().then(
            (response) => {
                setContent(response.data);
            },
            (error) => {
                const _content =
                    (error.response &&
                        error.response.data &&
                        error.response.data.message) ||
                    error.message ||
                    error.toString();
                setContent(_content);
            }
        );
        if (currentId && currentId.profile_img_complete) {
            setPhotoURL(currentId.profile_img_complete);
        }
    }, [currentId]);

    if (!currentUser) {
        return <Link to='/login' />;
    }
    return (
        <div className='page'>
            <div className='profile-container'>
                <header className='jumbotron'>
                    <h3>
                        <strong id='profile-name'>{currentUser.username}</strong> Profile
                    </h3>
                </header>

                <p>
                    <img src={photoURL} alt='Avatar' className='avatar'></img>
                    <strong>Token:</strong> {currentUser.accessToken.substring(0, 20)} ...{' '}
                    {currentUser.accessToken.substr(currentUser.accessToken.length - 20)}
                </p>
                <p>
                    <strong>Id:</strong> {currentUser.id}
                </p>
                <p>
                    <strong>Email:</strong> {currentUser.email}
                </p>
                <strong>Authorities:</strong>
                <ul>
                    {currentUser.roles &&
                        currentUser.roles.map((role, index) => <li key={index}>{role}</li>)}
                </ul>
                <button>
                    <Link to={'/profile/edit'}>Edit Profile</Link>
                </button>
            </div>
        </div>
    );
};
export default Profile;

auth.js:

// We’re gonna import AuthService to make asynchronous HTTP requests with trigger one or more dispatch in the result.

// – register(): calls the AuthService.register(username, email, password) & dispatch setMessage if successful/failed
// – login(): calls the AuthService.login(username, password) & dispatch setMessage if successful/failed
// – logout(): calls the AuthService.logout().

// setMessage is imported from message slice that we’ve created above.
// We also need to use Redux Toolkit createAsyncThunk which provides a thunk that will take care of the action types and dispatching the right actions based on the returned promise.
//There are 3 async Thunks to be exported:

// register
// login
// logout

import {createSlice, createAsyncThunk} from '@reduxjs/toolkit';
import {setMessage} from './messages';
import AuthService from '../services/auth.service';
const user = JSON.parse(localStorage.getItem('user'));
export const register = createAsyncThunk(
    'auth/register',
    async ({username, email, password}, thunkAPI) => {
        try {
            const response = await AuthService.register(username, email, password);
            thunkAPI.dispatch(setMessage(response.data.message));
            return response.data;
        } catch (error) {
            const message =
                (error.response &&
                    error.response.data &&
                    error.response.data.message) ||
                error.message ||
                error.toString();
            thunkAPI.dispatch(setMessage(message));
            return thunkAPI.rejectWithValue();
        }
    }
);
export const login = createAsyncThunk(
    'auth/login',
    async ({username, password}, thunkAPI) => {
        try {
            const data = await AuthService.login(username, password);
            return {user: data};
        } catch (error) {
            const message =
                (error.response &&
                    error.response.data &&
                    error.response.data.message) ||
                error.message ||
                error.toString();
            thunkAPI.dispatch(setMessage(message));
            return thunkAPI.rejectWithValue();
        }
    }
);
export const logout = createAsyncThunk('auth/logout', async () => {
    await AuthService.logout();
});
const initialState = user
    ? {isLoggedIn: true, user}
    : {isLoggedIn: false, user: null};
const authSlice = createSlice({
    name: 'auth',
    initialState,
    extraReducers: {
        [register.fulfilled]: (state, action) => {
            state.isLoggedIn = false;
        },
        [register.rejected]: (state, action) => {
            state.isLoggedIn = false;
        },
        [login.fulfilled]: (state, action) => {
            state.isLoggedIn = true;
            state.user = action.payload.user;
        },
        [login.rejected]: (state, action) => {
            state.isLoggedIn = false;
            state.user = null;
        },
        [logout.fulfilled]: (state, action) => {
            state.isLoggedIn = false;
            state.user = null;
        },
    },
});
const {reducer} = authSlice;
export default reducer;

user-profile.service.js:

import axios from 'axios';
import authHeader from './auth-header';
const API_URL = 'http://localhost:8080/';

const getProfile = () => {
    return axios.get(API_URL   'profile', {headers: authHeader()});
};

const user_profile = {
    getProfile,
};
export default user_profile;

CodePudding user response:

In your .then() of UserServices.getProfile() use the following:

setPhotoURL(response.data.profile_img_complete);

Also remove the following code from your useEffect:

if (currentId && currentId.profile_img_complete) {
  setPhotoURL(currentId.profile_img_complete);
}

Hope this helps :-)

CodePudding user response:

I'm assuming that the data in the image is the value of response.data that is returned by UserProfileService.getProfile(). You need to update the photoURL when the UserProfileService.getProfile() request is fulfilled. Besides, currentId is a string. It does not contain profile_img_complete attribute.

import React, {useState, useEffect} from 'react';
import {Link} from 'react-router-dom';
import {useSelector} from 'react-redux';
import UserProfileService from '../../services/user-profile.service';
import './styles/Profile.css';
const Profile = () => {
    const {user: currentUser} = useSelector((state) => state.auth);
    const {id: currentId} = useSelector((state) => state.auth);
    const [content, setContent] = useState('');
    const [photoURL, setPhotoURL] = useState('../../images/user-solid.svg');
 //user-solid is the default image I want if the profile image link is null
    useEffect(() => {
        UserProfileService.getProfile().then(
            (response) => {
                setContent(response.data);
                if (response.data.profile_img_complete) 
                  setPhotoURL(response.data.profile_img_complete);

            },
            (error) => {
                const _content =
                    (error.response &&
                        error.response.data &&
                        error.response.data.message) ||
                    error.message ||
                    error.toString();
                setContent(_content);
            }
        );
       
    }, [currentId]);

    if (!currentUser) {
        return <Link to='/login' />;
    }
    return (
        <div className='page'>
            <div className='profile-container'>
                <header className='jumbotron'>
                    <h3>
                        <strong id='profile-name'>{currentUser.username}</strong> Profile
                    </h3>
                </header>

                <p>
                    <img src={photoURL} alt='Avatar' className='avatar'></img>
                    <strong>Token:</strong> {currentUser.accessToken.substring(0, 20)} ...{' '}
                    {currentUser.accessToken.substr(currentUser.accessToken.length - 20)}
                </p>
                <p>
                    <strong>Id:</strong> {currentUser.id}
                </p>
                <p>
                    <strong>Email:</strong> {currentUser.email}
                </p>
                <strong>Authorities:</strong>
                <ul>
                    {currentUser.roles &&
                        currentUser.roles.map((role, index) => <li key={index}>{role}</li>)}
                </ul>
                <button>
                    <Link to={'/profile/edit'}>Edit Profile</Link>
                </button>
            </div>
        </div>
    );
};
export default Profile;

Alternate Solution

state.auth should already hold profile_img_complete. So, you can also do this

import React, {useState, useEffect} from 'react';
import {Link} from 'react-router-dom';
import {useSelector} from 'react-redux';
import UserProfileService from '../../services/user-profile.service';
import './styles/Profile.css';
const Profile = () => {
    const {user: currentUser} = useSelector((state) => state.auth);
    const auth = useSelector((state) => state.auth);
    const {id: currentId} = useSelector((state) => state.auth);
    const [content, setContent] = useState('');
    const [photoURL, setPhotoURL] = useState(auth.profile_img_complete || '../../images/user-solid.svg');
 //user-solid is the default image I want if the profile image link is null
    useEffect(() => {
        UserProfileService.getProfile().then(
            (response) => {
                setContent(response.data);
                if (response.data.profile_img_complete) 
                  setPhotoURL(response.data.profile_img_complete);
            },
            (error) => {
                const _content =
                    (error.response &&
                        error.response.data &&
                        error.response.data.message) ||
                    error.message ||
                    error.toString();
                setContent(_content);
            }
        );

    }, [currentId]);

    if (!currentUser) {
        return <Link to='/login' />;
    }
    return (
        <div className='page'>
            <div className='profile-container'>
                <header className='jumbotron'>
                    <h3>
                        <strong id='profile-name'>{currentUser.username}</strong> Profile
                    </h3>
                </header>

                <p>
                    <img src={photoURL} alt='Avatar' className='avatar'></img>
                    <strong>Token:</strong> {currentUser.accessToken.substring(0, 20)} ...{' '}
                    {currentUser.accessToken.substr(currentUser.accessToken.length - 20)}
                </p>
                <p>
                    <strong>Id:</strong> {currentUser.id}
                </p>
                <p>
                    <strong>Email:</strong> {currentUser.email}
                </p>
                <strong>Authorities:</strong>
                <ul>
                    {currentUser.roles &&
                        currentUser.roles.map((role, index) => <li key={index}>{role}</li>)}
                </ul>
                <button>
                    <Link to={'/profile/edit'}>Edit Profile</Link>
                </button>
            </div>
        </div>
    );
};
export default Profile;

CodePudding user response:

const image = req.query.profile_img or const {profile_img} = req.query

  • Related