skip to Main Content

I want to create a public profile page in my application, but whenever I hit a route, an error appears in the console. I can’t understand what a problem is, could you please look at it with your fresh eyes. Let me give you more info about my issue.

Public route – back-end

// @route  POST api/profile/user/:user_id
// @desc   Get profile by user ID
// @access Public
router.get('/user/:user_id', (req, res) => {
  const errors = {};
  Profile.findOne({ user: req.params.user_id })
    .populate('user', ['name', 'email', 'avatar'])
    .then(profile => {
      if (!profile) {
        errors.nonprofile = 'There is no profile for this user';
        res.status(404).json(errors);
      }
      res.json(profile);
    })
    .catch(err =>
      res.status(404).json({ profile: 'There is no profile for this user' })
    );
});

Redux action part

export const getPublicProfileByID = id => dispatch => {
  console.log(id);
  axios
    .get(`api/profile/user/${id}`)
    .then(res => {
      dispatch({
        type: GET_PUBLIC_PROFILE_BY_ID,
        payload: res.data
      });
    })
    .catch(err =>
      dispatch({
        type: GET_PUBLIC_PROFILE_BY_ID,
        payload: null
      })
    );
};

PublicProfile – react part

import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import Spinner from '../common/Spinner';
import { getPublicProfileByID } from '../../actions/profileActions';
import { Link } from 'react-router-dom';

class PublicProfile extends Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    console.log(this.props);
    this.props.getPublicProfileByID(this.props.profile._id);
  }

  render() {
    const { profile, loading } = this.props.profile;
    const { auth } = this.props;
    console.log(profile);
    let profileShow;

    if (profile === null || loading) {
      profileShow = <Spinner />;
    } else {
      profileShow = (
        <div className="row">
          <div className="col-md-4" align="center">
            <figure className="figure">
              <img
                src={auth.user.avatar}
                className="figure-img img-fluid rounded"
                alt={auth.user.avatar}
              />
            </figure>
          </div>
          <div className="col-md-6">{profile.bio}</div>
          <div className="col-md-2">
            <ul className="list-group list-group-flush">
              <li className="list-group-item">
                <div className="row">
                  <div className="col">
                    {profile.social ? (
                      <a href={profile.social.facebook} target="_blank">
                        <i className="fab fa-facebook" />
                      </a>
                    ) : null}
                  </div>
                  <div className="col">
                    {profile.social ? (
                      <a href={profile.social.vk} target="_blank">
                        <i className="fab fa-vk" />
                      </a>
                    ) : null}
                  </div>
                  <div className="col">
                    {profile.social ? (
                      <a href={profile.social.instagram} target="_blank">
                        <i className="fab fa-instagram" />
                      </a>
                    ) : null}
                  </div>
                </div>
              </li>
              {profile.country ? (
                <li className="list-group-item">Страна: {profile.country}</li>
              ) : null}
              {profile.city ? (
                <li className="list-group-item">Город: {profile.city}</li>
              ) : null}
              {profile.gender ? (
                <li className="list-group-item">Пол: {profile.gender}</li>
              ) : null}
              {profile.education ? (
                <li className="list-group-item">
                  Образование: {profile.education}
                </li>
              ) : null}
              {profile.languages ? (
                <li className="list-group-item">
                  Языки:{' '}
                  {profile.languages.map(language => (
                    <span key={language}>{language}</span>
                  ))}
                </li>
              ) : null}
            </ul>
          </div>
        </div>
      );
    }

    return (
      <div className="container">
        <div className="row">
          <div className="col align-self-center">{profileShow}</div>
        </div>
      </div>
    );
  }
}

PublicProfile.propTypes = {
  auth: PropTypes.object.isRequired,
  getPublicProfileByID: PropTypes.func.isRequired
};

const mapStateToProps = state => ({
  profile: state.profile,
  auth: state.auth
});

export default connect(
  mapStateToProps,
  { getPublicProfileByID }
)(PublicProfile);

Redux Reducer Part

import {
  GET_PROFILE,
  PROFILE_LOADING,
  CLEAR_CURRENT_PROFILE,
  GET_PUBLIC_PROFILE_BY_ID
} from '../actions/types';

const initialState = {
  profile: null,
  profiles: null,
  loading: false
};

export default function(state = initialState, action) {
  switch (action.type) {
    case PROFILE_LOADING:
      return {
        ...state,
        loading: true
      };
    case GET_PROFILE:
      return {
        ...state,
        profile: action.payload,
        loading: false
      };
    case GET_PUBLIC_PROFILE_BY_ID:
      return {
        ...state,
        profile: action.payload,
        loading: false
      };
    case CLEAR_CURRENT_PROFILE:
      return {
        ...state,
        profile: null
      };
    default:
      return state;
  }
}

Public route in app.js

<Route exact path="/leaders/:id" component={PublicProfile} />

URL in the browser
enter image description here

Error in the console
enter image description here

3

Answers


  1. Chosen as BEST ANSWER

    I have solved the issue, I should have used findById method, and params should have been req.params.id. So a valid code looks like this.

    // @route  POST api/profile/user/:user_id
    // @desc   Get profile by user ID
    // @access Public
    
    router.get('/user/:id', (req, res) => {
      const errors = {};
      Profile.findById(req.params.id)
        .populate('user', ['name', 'email', 'avatar'])
        .then(profile => {
          if (!profile) {
            errors.nonprofile = 'There is no profile for this user';
            res.status(404).json(errors);
          }
          res.json(profile);
        })
        .catch(err =>
          res.status(404).json({ profile: 'There is no profile for this user' })
        );
    });
    

  2. You are confusing your front end URL with backend Restful http URL,
    you need to start different two ports for both react and node app,
    You are mixing logic of React-Route with node-Express logic,
    when localhost:3000 stands for react,
    you should choose different port number for backend app,
    keep server listening on that port,
    then make req to that urls and communicate your data.
    You need to configure your app properly.
    eg.
    localhost:3000/leaders/leader/2 for your front end,
    make server request like,
    localhost:8000/api/profile/user/2 where 2 is ${id} for backend code.

    Login or Signup to reply.
  3. Just one issue I noticed, in your api route, it wants to find a Profile who’s user field matches the parameter you passed.

    router.get('/user/:user_id', (req, res) => {
      const errors = {};
      Profile.findOne({ user: req.params.user_id })
    

    However it looks like you are passing in the wrong value in your action-creator. You’re passing in the id of the profile.

      componentDidMount() {
        console.log(this.props);
        this.props.getPublicProfileByID(this.props.profile._id);
      }
    

    Instead, you need to pass in the id of the user who owns this profile.

      componentDidMount() {
        console.log(this.props);
        this.props.getPublicProfileByID(this.props.profile.user._id);
      }
    

    Second, there appears to be an error with your axios call

      axios
        .get(`api/profile/user/${id}`)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search