mongodb TypeError:无法在react中读取null的属性“name”

hl0ma9xz  于 2023-03-17  发布在  Go
关注(0)|答案(6)|浏览(111)

我是新的React和redux,所以我不能解决这个错误后,做了大量的研究很容易。我试图在一个单独的页面中显示用户的个人资料的形式卡,但我得到一个错误:

TypeError: Cannot read property 'name' of null
ProfileItem.render
src/components/profiles/Profileitem.js:15
  12 | <div className="row">
  13 |   
  14 |   <div className="col-lg-6 col-md-4 col-8">
> 15 |     <h3>{profile.user.name}</h3>
  16 |     <p>
  17 |       {profile.status}{' '}
  18 |       {isEmpty(profile.company) ? null : (

▶ 22 stack frames were collapsed.
(anonymous function)
src/actions/userprofileAction.js:77
  74 | dispatch(profileLoading());
  75 | axios
  76 |   .get('/api/userprofile/all')
> 77 |   .then(res =>
  78 |     dispatch({
  79 |       type: GET_PROFILES,
  80 |       payload: res.data

//这是用户配置文件userprofile.js的后端

const express = require('express');
const router = express.Router();
const mongoose=require('mongoose');
const passport=require('passport');

//loading validation after creating the userprofie valdiation
const validateProfileInput=require('../../validation/userprofile');
const validateExperienceInput=require('../../validation/experience');
//bring profile schema model

const Profile=require('../../models/Profile');

//bringing user schema model
const User=require('../../models/User');

//testing this api 
router.get('/demo', (req, res) => res.json({ msg: 'Profile Works' }));
//get request
//now need to check for the user who is trying to login
router.get('/',passport.authenticate('jwt', { session: false }),(req, res) => {
    //initializing this as empty because need to add error msg   
    const errors = {};
//fetch current user's profile and finding from profile model
//findone is a mongoose method which will find a specifc{single} thing
        Profile.findOne({ user: req.user.id }) .populate('user', ['name']).then(profile => {
           //if not found display error msg
            if (!profile) {
              errors.noprofile = 'no profile exists for this person';
              return res.status(404).json(errors);
            }
            //if found then show proifle
            res.json(profile);
          })
          .catch(err => res.status(404).json(err));
      }
    )
//to see all profiles at api/userprofile/all
    router.get('/all',(req,res)=>{
        Profile.find()
        .populate('user',['name'])
        .then(profiles=>{
            if(!profiles){
                errors.noprofile='no profiles';
                return res.status(404).json(errors);
            }
            res.json(profiles);
        })
        .catch(err=>res.status(404).json({profile:'no profiles'}));
    })
//getting profile by name
    router.get('/profilename/:profilename',(req,res)=>{
        Profile.findOne({profiename:req.params.profiename})
        .populate('user',['name'])
        .then(profile=>{
            if(!profile){
                errors.noprofile='there is no profile';
                res.status(400).json(errors);
            }
            res.json(profile);
        })
        .catch(err=>res.status(404).json(err));
    })
//getting profile by id
    router.get('/users/:users_id',(req,res)=>{
        Profile.findOne({profiename:req.params.profiename})
        .populate('user',['name'])
        .then(profile=>{
            if(!profile){
                errors.noprofile='there is no profile';
                res.status(400).json(errors);
            }
            res.json(profile);
        })
        .catch(err=>res.status(404).json(err));
    })
//post request
    router.post(
        '/',
        passport.authenticate('jwt', { session: false }),
        (req, res) => {
        const {errors,isValid}=validateProfileInput(req.body);

        //check validation
        if(!isValid){
            return res.status(400).json(errors);
        }
        //getting fields and adding in an obj
        const fields={};
        fields.user=req.user.id;

        //checking if its sent from handle
        if(req.body.profilename)fields.profilename=req.body.profilename;
        if(req.body.company)fields.company=req.body.company;
        if(req.body.location)fields.location=req.body.location;

        //so splitting skills into an array when seperated by ','
        if(typeof req.body.skills!=='undefined')
            fields.skills=req.body.skills.split(',');

//searching by id and if profile has then update

        Profile.findOne({user:req.user.id}).then(profile=>{
            if(profile){
                Profile.findOneAndUpdate({user:req.user.id},{$set:fields},{new:true})
                .then(profile=>res.json(profile));
            }
            else{
                //checking if there
                Profile.findOne({profiename:fields.profilename}).then(profile=>{
                    if(profile){
                        errors.profiename='profile already there'
                        res.status(400).json(errors);
                    }
                    //saving  and making new if not
                    new Profile(fields).save().then(profile=>res.json(profile));
                })
            }
        })
          }
        );

//post req to add exp
router.post(
    '/experience',
    passport.authenticate('jwt', { session: false }),
    (req, res) => {
      const { errors, isValid } = validateExperienceInput(req.body);

      // Check Validation
      if (!isValid) {
        // Return any errors with 400 status
        return res.status(400).json(errors);
      }
  //to add new experience
      Profile.findOne({ user: req.user.id }).then(profile => {
        const newExperience = {
          title: req.body.title,
          company: req.body.company,
          location: req.body.location,
          from: req.body.from,
          to: req.body.to,

          description: req.body.description
        };

        // Add to exp array
        profile.experience.unshift(newExperience);

        profile.save().then(profile => res.json(profile));
      });
    }
  );

  //after adding if user wants to delete the experience
  router.delete(
    '/experience/:exp_id',
    passport.authenticate('jwt', { session: false }),
    (req, res) => {
      const { errors, isValid } = validateExperienceInput(req.body);

      // Check Validation
      if (!isValid) {
        // Return any errors with 400 status
        return res.status(400).json(errors);
      }

      Profile.findOne({ user: req.user.id }).then(profile => {
        const remove=profile.experience
        .map(item=>item.id)
        .indexof(req.params.exp_id);
        //splicing out of array at index 1
        profile.experience.splice(remove,1)

        //saving
        profile.save().then(profile=>res.json(profile));
      })
      .catch(err=>res.status(404).json(err));
    }
  );

module.exports = router;

userprofileaction.js

import axios from 'axios';
import {GET_USERPROFILE,PROFILE_LOADING,GET_ERRORS,CLEAR_CURRENT_PROFILE,GET_PROFILES} from './types';

//getting current profile
export const getProfile=()=>dispatch=>{
    //dispatching loading state before req
    dispatch(profileLoading());
    axios.get('/api/userprofile')
    .then(res=>
    dispatch({
        type:GET_USERPROFILE,
        payload:res.data
    }))
    .catch(err=>
    dispatch({
        type:GET_USERPROFILE,
        payload:{}
    }))
}

 // Create Profile
export const createProfile = (profileData, history) => dispatch => {
    axios
      .post('/api/userprofile', profileData)
      .then(res => history.push('/dashboard'))
      .catch(err =>
        dispatch({
          type: GET_ERRORS,
          payload: err.response.data
        })
      );
  };
  export const addExp=(experienceData,history)=>dispatch=>{
      axios.post('/api/userprofile/experience',experienceData)
      .then(res=>history.push('/dashboard'))
      .catch(err=>dispatch({
          type:GET_ERRORS,
          payload:err.response.data
      }))
  }

  export const deleteExperience = id => dispatch => {
    axios
      .delete(`/api/userprofile/experience/${id}`)
      .then(res =>
        dispatch({
          type: GET_USERPROFILE,
          payload: res.data
        })
      )
      .catch(err =>
        dispatch({
          type: GET_ERRORS,
          payload: err.response.data
        })
      );
  };
//loading the profile
export const profileLoading=()=>{
    return{
        type:PROFILE_LOADING
    }
}
//clearing profile
export const clearcurrentprofile=()=>{
    return{
        type:CLEAR_CURRENT_PROFILE
    }
}

//getting profiles
export const getProfiles = () => dispatch => {
    dispatch(profileLoading());
    axios
      .get('/api/userprofile/all')
      .then(res =>
        dispatch({
          type: GET_PROFILES,
          payload: res.data
        })
      )
      .catch(err =>
        dispatch({
          type: GET_PROFILES,
          payload: null
        })
      );
  };

profileItem.js

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import isEmpty from '../../validation/is-empty';

class ProfileItem extends Component {
  render() {
    const { profile } = this.props;

    return (
      <div className="card card-body bg-light mb-3">
        <div className="row">

          <div className="col-lg-6 col-md-4 col-8">
            <h3>{profile.user.name}</h3>
            <p>
              {profile.status}{' '}
              {isEmpty(profile.company) ? null : (
                <span>at {profile.company}</span>
              )}
            </p>
            <p>
              {isEmpty(profile.location) ? null : (
                <span>{profile.location}</span>
              )}
            </p>
            <Link to={`/userprofile/${profile.profilename}`} className="btn btn-info">
              View Profile
            </Link>
          </div>
          <div className="col-md-4 d-none d-md-block">
            <h4>Skill Set</h4>
            <ul className="list-group">
              {profile.skills.slice(0, 4).map((skill, index) => (
                <li key={index} className="list-group-item">
                  <i className="fa fa-check pr-1" />
                  {skill}
                </li>
              ))}
            </ul>
          </div>
        </div>
      </div>
    );
  }
}

ProfileItem.propTypes = {
  profile: PropTypes.object.isRequired
};

export default ProfileItem;

Profiles.js

import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';

import ProfileItem from './ProfileItem';
import { getProfiles } from '../../actions/userprofileAction';

class Profiles extends Component {
  componentDidMount() {
    this.props.getProfiles();
  }

  render() {
    const { profiles, loading } = this.props.profile;
    let profileItems;

    if (profiles === null || loading) {
      profileItems = <h3>Profiles are loading..........</h3>;
    } else {
      if (profiles.length > 0) {

        profileItems = profiles.map(profile => (
          <ProfileItem key={profile._id} profile={profile} />
        ));
      } else {
        profileItems = <h4>No profiles found.....</h4>;
      }
    }

    return (
      <div className="profiles">
        <div className="container">
          <div className="row">
            <div className="col-md-12">
              <h1 className="display-4 text-center">Job Seeker's profiles</h1>
              <p className="lead text-center">
                Explore and get in touch with a Job seeker for free!
              </p>
              {profileItems}
            </div>
          </div>
        </div>
      </div>
    );
  }
}

Profiles.propTypes = {
  getProfiles: PropTypes.func.isRequired,
  profile: PropTypes.object.isRequired
};

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

export default connect(mapStateToProps, { getProfiles })(Profiles);

userprofileReducer.js

import {GET_USERPROFILE,PROFILE_LOADING,CLEAR_CURRENT_PROFILE,GET_PROFILES} from '../actions/types';
//import { stat } from 'fs';
const initialstate={
    //will have profile
    profile:null,
    profiles:null,
    loading:false
}

export default function(state=initialstate, action){
    switch(action.type){
        case PROFILE_LOADING:
        return{
            ...state,
            loading:true
        }
        case GET_USERPROFILE:
        return{
            ...state,
            profile:action.payload,
            loading:false
        }
        case GET_PROFILES:
        return{
            ...state,
            profiles:action.payload,
            loading:false
        }
        case CLEAR_CURRENT_PROFILE:
        return{
            ...state,
            profile:null
        }
        default:
        return state;

    }
}
zour9fqk

zour9fqk1#

你首先需要检查profile是未定义的还是空的,然后才能访问它的键。在这种情况下,你通常会使用三元或&&运算符。
下面的代码应该适合您

class ProfileItem extends Component {
     render() {
         const { profile } = this.props;
         return (
          <div className="card card-body bg-light mb-3">
               <div className="row">
               {profile && (
               <div className="col-lg-6 col-md-4 col-8">
                   <h3>{profile.user && profile.user.name}</h3>
                   <p>
                   {profile.status}{' '}
                   {isEmpty(profile.company) ? null : (
                   <span>at {profile.company}</span>
                    )}
                  </p>
                  <p>
                  {isEmpty(profile.location) ? null : (
                     <span>{profile.location}</span>
                   )}
                  </p>
                  <Link to={`/userprofile/${profile.profilename}`} className="btn btn-info">
          View Profile
                 </Link>
              </div>
               <div className="col-md-4 d-none d-md-block">
                 <h4>Skill Set</h4>
                 <ul className="list-group">
                    {profile.skills.slice(0, 4).map((skill, index) => (
                      <li key={index} className="list-group-item">
                       <i className="fa fa-check pr-1" />
                          {skill}
                      </li>
                    ))}
                 </ul>
                  </div>
                      )}
                </div>
            </div>
           );
        }
      }

     ProfileItem.propTypes = {
            profile: PropTypes.object.isRequired
      };

      export default ProfileItem;
yyhrrdl8

yyhrrdl82#

看起来您在设置值之前尝试正确读取。尝试在调用它之前添加检查。类似于:

if(profile.user !== 'null'){
   ...
}
cx6n0qe3

cx6n0qe33#

尝试console.log(这个.props)在进入render的第一件事。
通常,当初始渲染完成且 prop 中的值尚不存在时,会出现此类错误。
解决方案是检查此.props和this.props.xxx,如果它们为空,则显示a“正在加载”消息/ a微调框。

jmp7cifd

jmp7cifd4#

当错误突出显示时,错误位于以下行:

<h3>{profile.user.name}</h3>

您正在尝试访问对象用户的名称,但问题是该对象与您预期的不同。其值为null,因此不包含属性名称。您需要在用户中填充服务响应的位置进行调试。

13z8s7eq

13z8s7eq5#

对我来说,我已经涵盖了try catch块,它的工作

let TOKEN =""
try{
   TOKEN = JSON.parse(JSON.parse(localStorage.getItem("persist:root")).user).currentUser.accessToken ;
}
catch(err){
    console.log(err);
}
nuypyhwy

nuypyhwy6#

嗨,现在重播已经晚了,你可以使用三元运算符,这将是最简单的解决方案。感谢@Dmytro Huz

{profile?.user?.name}

相关问题