You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修复React Native中TypeError: null is not an object错误求助

问题排查:TypeError: null is not an object (evaluating 'JSON.parse(value).token')

我遇到了如下错误:LOG [TypeError: null is not an object (evaluating 'JSON.parse(value).token')],已检查代码拼写且后端服务正常运行,希望有人帮忙排查代码问题。相关代码如下:

Profile组件代码

import { StyleSheet, View, StatusBar, Text, Image, ActivityIndicator } from 'react-native';
import React, { useEffect, useState } from 'react';
import ButtomNavbar from '../../Components/ButtomNavbar';
import TopNavbar from '../../Components/TopNavbar';
import { formHead } from '../../CommonCss/FormCss';
import { ScrollView } from 'react-native-gesture-handler';
import defaultprofileimg from '../../../assets/profileimg.jpg';
import AsyncStorage from '@react-native-async-storage/async-storage';

const Profile = ({ navigation }) => {

  const [userdata, setUserdata] = useState(null)

  useEffect(() => {
    AsyncStorage.getItem('user')
      .then(async (value) => {
        fetch('http://10.0.2.2:3000/userdata', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Authorization' : 'Bearer' + JSON.parse(value).token
          },
          body: JSON.stringify({ email: JSON.parse(value).user.email })
        })
          .then(res => res.json()).then(data => {
            if (data.message == 'User Data Fetched Susscessfully') {
              setUserdata(data.user)
            }
            else {
              alert('Something went wrong')
              navigation.navigate('login')
            }
          })
          .catch(err => {
            alert(err)
            console.log(err)
          })
      })
      .catch(err => {
        alert(err)
        console.log(err)
      })
  }, [])

  console.log(userdata)
  return (
    <View style={styles.container}>
      <StatusBar />
      <ButtomNavbar navigation={navigation} page={'profile'} />
      <TopNavbar navigation={navigation} page={'profile'} />
      {
        userdata? <ScrollView>
        <View style={styles.section1}>
          {
            userdata.profileImg.length>0 ? 
            <Image style={styles.profileimg} source={{ uri: userdata.profileImg}} /> 
            :
            <Image style={styles.profileimg} source={defaultprofileimg} />
          }
          <Text style={styles.usernameText}>@{userdata.username}</Text>
          <View style={styles.Postrow}>
            <View style={styles.Postrow1}>
              <Text style={styles.followerTxt}>UpVotes</Text>
              <Text style={styles.UpVote}>{userdata.upvotes.length}</Text>
            </View>
            <View style={styles.verticalLine}></View>
            <View style={styles.Postrow1}>
              <Text style={styles.followerTxt}>DownVotes</Text>
              <Text style={styles.UpVote}>{userdata.donwvotes.length}</Text>
            </View>
            <View style={styles.verticalLine}></View>
            <View style={styles.Postrow1}>
              <Text style={styles.followerTxt}>Posts</Text>
              <Text style={styles.UpVote}>{userdata.posts.length}</Text>
            </View>
          </View>
          {/* <Text style={styles.decs}>Hello this is des</Text> */}
        </View>
       {
        userdata.posts.length > 0 ?  <View style={styles.section1}>
        <Text style={styles.postTxt}>Your Posts</Text>
        <View style={styles.posts}>
          {
            userdata.posts.map((item) => {
              return (
                <Image key={item.id} style={styles.Postimage} source={{ uri: item.posts }} />
              )
            })
          }
        </View>
      </View>
      :
      <View style={styles.noPost}>
        <Text style={styles.noposttxt}>User not posted anything yet</Text>
      </View>
       }
      </ScrollView> 
      : 
      <ActivityIndicator color='white' size='large' />

      }
    </View>

  )
}

export default Profile

后端/userdata接口代码

router.post('/userdata', (req, res) => {
    const { authorization } = req.headers;

    if (!authorization) {
        return res.status(401).json({ error: 'You must be logged in, token not given' });
    }

    const token = authorization.replace("Bearer", "");
    console.log(token);

    jwt.verify(token, process.env.JWT_SECERT, (err, payload) => {
        if (err) {
            return res.status(401).json({ error: 'You must be logged in, token invalid' })
        }

        const { _id } = payload;
        User.findById(_id).then(
            userdata => {
                res.status(200).send({ message: 'User Found', user: userdata })
            })
    })


})

登录逻辑代码

const handleLogin = () => {
    if (email == '' || password == '') {
        alert('Please enter email and password')
    }
    else {
        setLoading(true)
        fetch('http://10.0.2.2:3000/login', { // for emultor 'http://10.0.2.2:3000/signup
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                email,
                password
            })
        })
            .then(res => res.json())
            .then(async data => {
                if (data.error) {
                    setLoading(false)
                    alert(data.error)
                }
                else if (data.message == 'Successfully Signed In') {
                    setLoading(false)
                    await AsyncStorage.setItem('user', JSON.stringify(data))
                    navigation.navigate('home', { data })
                }
            })
            .catch(err => {
                setLoading(false)
                alert(err)
            })
    }

  }

后端/login接口代码

router.post('/login', (req, res) => {
    const { email, password } = req.body;

    if (!email || !password) {
        return res.status(422).json({ error: 'Please fill all the fields' })
    }

    else {
        User.findOne({ email: email })
            .then(savedUser => {
                if (!savedUser) {
                    return res.status(422).json({ error: 'invaile cnreditnions' })
                }
                else {
                    bcrypt.compare(password, savedUser.password)
                        .then(
                            doMatch => {
                                if (doMatch) {
                                    const token = jwt.sign({ _id: savedUser._id }, process.env.JWT_SECERT);

                                    const { _id, username, email } = savedUser;

                                    res.json({ message: 'Successfully Signed In', token, user: { _id, username, email } });
                                }
                                else {
                                    return res.status(422).json({ error: 'invaile cnreditnions' })
                                }
                            }

                        )
                }
            })
            .catch(err => {
                console.log(err)
            })
    }
})

错误原因及修复方案

1. 核心错误:AsyncStorage返回null导致JSON.parse失败

错误直接出在JSON.parse(value).token,说明AsyncStorage.getItem('user')拿到的value是null——可能是用户未登录直接进入Profile页面,或者登录时存储操作失败。

修复:
在Profile组件的useEffect中先判断value是否存在,再执行后续逻辑,同时避免重复JSON.parse:

useEffect(() => {
  AsyncStorage.getItem('user')
    .then(async (value) => {
      if (!value) {
        alert('请先登录')
        navigation.navigate('login')
        return
      }
      const savedUser = JSON.parse(value)
      fetch('http://10.0.2.2:3000/userdata', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': 'Bearer ' + savedUser.token
        },
        body: JSON.stringify({ email: savedUser.user.email })
      })
      .then(res => res.json())
      .then(data => {
        if (data.message === 'User Found') {
          setUserdata(data.user)
        } else {
          alert('获取用户数据失败')
          navigation.navigate('login')
        }
      })
      .catch(err => {
        alert(err.message)
        console.log(err)
      })
    })
    .catch(err => {
      alert(err.message)
      console.log(err)
    })
}, [])

2. Authorization头格式不规范

后端用authorization.replace("Bearer", "")截取token,但前端原代码是'Bearer' + token(无空格),会导致token前带有多余字符,引发JWT验证失败。

修复:
前端Authorization头改成'Bearer ' + savedUser.token(Bearer后加空格,符合JWT规范),后端也可以同步调整为replace("Bearer ", ""),匹配更准确。

3. 字符串匹配错误

Profile组件中判断data.message == 'User Data Fetched Susscessfully',但后端/userdata接口返回的是{ message: 'User Found' },两者不匹配会导致误跳登录页。

修复:
将判断条件改为data.message === 'User Found'。

4. 拼写错误

Profile组件中userdata.donwvotes.length是拼写错误,应为userdata.downvotes.length,否则会触发新的类型错误。


内容的提问来源于stack exchange,提问作者user20785876

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 07:05:43