React.js this.props未定义,除非刷新页面

时间:2020-11-11 09:03:54

标签: javascript reactjs react-props

因此,我遇到以下问题,我试图显示用户在用户个人资料中发表的所有帖子。如果我从登录开始并转到配置文件,则会出现以下错误:this.props.user [0] .id未定义。但是,如果刷新页面(有时刷新两次),则效果很好。

我已经在线搜索过,只能看到相反的情况(刷新时道具未定义),我找不到解决方案。

这是我的代码:

import React from "react";
import axios from "axios";
import { Card, CardBody, CardTitle, CardText} from "reactstrap";
import Withuser from "./Withuser"

class Profile extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      thoughts: []
    }
  }

  componentDidMount = () => {
    this.getShares()
  }

  getShares = () => {
    const user_id = this.props.user[0].id
    console.log(this.props.user[0].id)

    axios(`http://localhost:7001/api/profile/shares/${user_id}`)

    .then(res => {
      console.log(res.data)
      this.setState(state => ({
        thoughts: res.data,
        loggedIn: !state.loggedIn
      }))
    })
    .catch(error => {
      this.setState({ error: true })
    })
  }

  render() {
    const { thoughts } = this.state
    return(
    <div>
      <h1>Your posts</h1>
      <ul>
        {thoughts.map((thought, index) => {
          return (
            <Card className='thoughts' key={index}>
              <CardBody>
                <CardTitle>{thought.user_name} posted at {thought.createdAt}</CardTitle>
                <CardText>{thought.body}</CardText>
              </CardBody>
            </Card>
          )
        })}
      </ul>
    </div>
    )
  }
}


export default Withuser(Profile, { renderNull: true });
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Withuser组件:

import React, { useState, useEffect } from 'react'
import axios from 'axios'

const withUser = (Component, options = { renderNull: true }) => props => {
  const [userData, setUserData] = useState(null)
  const [userId, setUserId] = useState(null)
  const [error, setError] = useState(false)

  useEffect(() => {
    const token = localStorage.getItem('token')
    if (!token) return
    axios('http://localhost:7001/api/profile', {
      headers: {
        'x-access-token': token,
      },
    })
      .then(response => {
        const id = response.data.id
        setUserId(id)
      })
      .catch(error => {
        setError(true)
        console.log(error)
      })
  }, [])

  useEffect(() => {
    axios(`http://localhost:7001/api/users/${userId}`)
      .then(response => {
      
      setUserData(response.data)
    })
  }, [userId])

  if (!userData && options.renderNull) return null
  return <Component {...props} user={userData} />
}

export default withUser
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

这是刷新时的控制台: enter image description here

您能看到错误在哪里吗?

任何帮助将不胜感激:)

2 个答案:

答案 0 :(得分:0)

可以通过在HOC中添加加载状态来解决此问题,以便在获取数据之前不呈现包装的组件。

const withUser = (Component, options = { renderNull: true }) => props => {
  const [userData, setUserData] = useState(null);
  const [userId, setUserId] = useState(null);
  const [error, setError] = useState(false);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    const token = localStorage.getItem('token');
    if (!token) return;
    setLoading(true); // set the loading state before api call is made
    axios('http://localhost:7001/api/profile', {
      headers: {
        'x-access-token': token,
      },
    })
      .then(response => {
        const id = response.data.id;
        setUserId(id);
      })
      .catch(error => {
        setError(true);
        console.log(error);
      })
      .finally(() => {
        setLoading(false); // reset loading state after api call is done
      });
  }, []);

  useEffect(() => {
    setLoading(true); // set the loading state before api call is made
    axios(`http://localhost:7001/api/users/${userId}`).then(response => {
      setUserData(response.data);
    }).finally(() => setLoading(false)); // reset loading state after api call is done
  }, [userId]);

  if (loading) return null; // Or render a loading indicator
  if (!userData && options.renderNull) return null;
  return <Component {...props} user={userData} />;
};

答案 1 :(得分:0)

这是因为在useEffect中,axios是一个异步调用,

const withUser = (Component, options = { renderNull: true }) => props => {
  ...
  useEffect(() => {
    axios(`http://localhost:7001/api/users/${userId}`)
      .then(response => {
      
      setUserData(response.data)
    })
  }, [userId])

快速可靠的解决方案是在Profile组件上添加默认道具

Profile.defaultProps = {
  user: [],
}

并必须检查

  getShares = () => {
    if(props.user.length === 0) return