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:无法读取未定义 Firebase 存储反应的属性“参考”