TypeError:无法在反应中读取 null 的属性“名称”

Posted

技术标签:

【中文标题】TypeError:无法在反应中读取 null 的属性“名称”【英文标题】:TypeError: Cannot read property 'name' of null in react 【发布时间】:2019-02-16 22:27:21 【问题描述】:

我是 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的后端 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 specifcsingle 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;

    

【问题讨论】:

【参考方案1】:

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

if(profile.user !== 'null')
   ...

【讨论】:

【参考方案2】:

在进入渲染时首先尝试 console.log(this.props)。

通常在初始渲染完成并且道具中的值尚不存在时会出现此类错误。

解决方案是检查 this.props 和 this.props.xxx,如果它们为 null,则显示“正在加载”消息/微调器。

【讨论】:

【参考方案3】:

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

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

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

【讨论】:

【参考方案4】:

您首先需要检查配置文件是否未定义或为空,然后才能访问其密钥。对于这种情况,您将主要使用三元或 && 运算符。

下面的代码应该适合你

  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;

【讨论】:

我错过了为用户添加条件。我更新了答案,现在可以使用了 很高兴为您提供帮助。如果可以解决您的问题,请点赞并接受答案。【参考方案5】:

对我来说,我已经在 try catch 块中介绍过并且它有效

let TOKEN =""
try
   TOKEN = JSON.parse(JSON.parse(localStorage.getItem("persist:root")).user).currentUser.accessToken ;

catch(err)
    console.log(err);

  

【讨论】:

以上是关于TypeError:无法在反应中读取 null 的属性“名称”的主要内容,如果未能解决你的问题,请参考以下文章

TypeError:无法读取 null 的属性(读取“1”)

TypeError:无法读取 null React Apollo 测试的属性“createEvent”

TypeError:无法读取反应中未定义的属性“减少”

TypeError:无法读取未定义 Firebase 存储反应的属性“参考”

未处理的拒绝(TypeError):无法读取反应中未定义的属性“setState”(firestore)

尝试通过反应上传到 Firebase 存储。 TypeError:无法读取未定义的属性(读取'ref')