【问题标题】:How to use react stateless component when API response didn't got yet?当 API 响应尚未得到时如何使用 React 无状态组件?
【发布时间】:2019-08-10 12:04:17
【问题描述】:

我在 Laravel 中使用 react,我正在尝试构建一个简单的 FriendsList 组件来显示来自 API 的数据。 问题是 Parent (Profile) 组件在获取数据之前已经完成加载,所以 FriendsList 组件返回错误,因为 props 是第一次为空。重要的是要说,无论 API 响应如何——父(配置文件)组件运行良好,它第一次加载为空——然后数据正在添加。

API 调用

 export const getProfile = () => {
 return axios
     .get('api/profile', {
        headers: { Authorization: `Bearer ${localStorage.usertoken}` }
     })
    .then(response => {
        // console.log(response.data)
        return response.data
    })
    .catch(err => {
        console.log(err)
    })
 }

父组件

        import React, { Component } from 'react'
        import { getProfile } from './UserFunctions'
        import FriendsList from './FriendsList';

        class Profile extends Component {
            constructor() {
                super()
                this.state = {
                    name: '',
                    hobbies: '',
                    user_bday: '',
                    members: [],
                    error: '',

                }

            }

            componentDidMount() {

                getProfile().then(res => {
                    //   console.log(JSON.parse(res))
                    this.setState({
                        name: res.user.name,
                        hobbies: res.user.hobbies,
                        user_bday: res.user.user_birthday,
                        related_friends: res.user.related_friends,
                        members: res.user.members,

                    })

                })
            }


            render() {

                return (
                    <div className="container">
                        <div className="jumbotron mt-5">
                            <div className="col-sm-4 mx-auto">
                                <h1 className="text-center">PROFILE</h1>
                            </div>
                            <table className="table col-md-4 mx-auto">
                                <tbody>
                                    <tr>
                                        <td>Name</td>
                                        <td>{this.state.name}</td>
                                        <td>{this.state.hobbies}</td>
                                        <td>{this.state.user_bday}</td>

                                    </tr>
                                </tbody>
                            </table>
                            <FriendsList members={this.state.members}> 
       </FriendsList>
                        </div>
                    </div>
                )
            }
        }

        export default Profile

    import React from 'react';
     class FriendsList extends React.Component {

      render() {
        console.log(this.props)
        const { members } = this.props;
        const listmembers = members.map((item, index) => (
          <li key={item + index}>{item.name}</li>
        ));
        return (
          <div>
            {listmembers}
          </div>
        );
      }
    }
    export default FriendsList

【问题讨论】:

  • 为什么不将初始members 状态设置为空数组而不是字符串?
  • 您是否应该利用 state 的 members 属性向 friends 属性提供数据?

标签: reactjs axios


【解决方案1】:

有几种方法可以解决这个问题。

第一种方法:

class Profile extends Component {
  render() {
    // check if your `state` has all the necessary values
    // before rendering your JSX

    const { name, hobbies, user_bday, members } = this.state
    const shouldRender = name !== '' && 
      hobbies !== '' &&
      user_bday !== '' &&
      Array.isArray(members) && members.length > 0

    if (!shouldRender) {
      return null;
    }
    return (...)
  }
}

这样,当您的state 拥有您需要的一切时,您只会渲染JSX


第二种方法:

class Profile extends Component {
  constructor() {
    // ...
    this.setState = {
      members: []
    }
  }
}

将您的members 设置为一个空数组,而不是一个空字符串,这样当您将它作为prop 传递给FriendList 组件时,调用this.props.friends.map 实际上是正确的,但它不会t 渲染任何东西,因为数组最初是空的。


此外,在 API 调用完成后,您似乎永远不会更新您的 members

componentDidMount() {
  getProfile().then(res => {
    this.setState({
      name: res.user.name,
      hobbies: res.user.hobbies,
      user_bday: res.user.user_birthday,
      related_friends: res.user.related_friends,
    })
  })
}

所以你的members 实际上是一个空字符串。确保使用正确的类型更新状态,在这种情况下应该是数组。

【讨论】:

  • 谢谢 - 我做了其他事情 - 但你的评论帮助我更好地理解了问题
【解决方案2】:

如果我理解你的问题,我想你需要看看https://www.npmjs.com/package/prop-types,我认为你的问题在于默认的 props 值,这个库可以帮助你实现想要的行为。

【讨论】:

    【解决方案3】:

    如果我正确理解了您所说的问题null props...此外,cmets 中的 Kellen 是正确的...您应该将成员设置为空数组,而我看不到您更新状态setState中的成员...

    试试:

    render() {
        const friendsList =
            this.props.firends &&
            this.props.friends.map(function(item, index) {
                <li key={index}>{item.name}</li>;
            });
    
        return (
            <div>
                <ul>{friendsList}</ul>
            </div>
        );
    }
    

    【讨论】:

      【解决方案4】:

      这里的另一种方法是使用loading 状态,在此期间您将显示加载指示器等。

      class Profile extends Component {
        constructor() {
          super();
          this.state = {
            name: "",
            hobbies: "",
            user_bday: "",
            members: "",
            error: "",
            isMembers: false,
            loading: true // Add loading state
          };
        }
      
        componentDidMount() {
          getProfile().then(res => {
            //   console.log(JSON.parse(res))
            this.setState({
              name: res.user.name,
              hobbies: res.user.hobbies,
              user_bday: res.user.user_birthday,
              related_friends: res.user.related_friends,
              loading: false // Remove the loading state when data is fetched
            });
          });
        }
      
        render() {
          return this.state.loading ? (
            <p> Loading... </p>
          ) : (
            <div className="container">
              <div className="jumbotron mt-5">
                <div className="col-sm-4 mx-auto">
                  <h1 className="text-center">PROFILE</h1>
                </div>
                <table className="table col-md-4 mx-auto">
                  <tbody>
                    <tr>
                      <td>Name</td>
                      <td>{this.state.name}</td>
                      <td>{this.state.hobbies}</td>
                      <td>{this.state.user_bday}</td>
                    </tr>
                  </tbody>
                </table>
                {/*<FriendsList friends={this.state.members}></FriendsList>*/}
              </div>
            </div>
          );
        }
      }
      
      

      【讨论】:

      • 谢谢 - 由于某种原因 FriendsList 组件中的道具没有更新 - 我没有收到任何错误,但看起来父组件正在更新 - 孩子的道具没有。 ...
      • 您需要更新您的问题并展示您如何传递这些道具。我可以看到您在子组件中迭代this.props.friends,但是父组件在状态上没有这样的道具。
      猜你喜欢
      • 2023-03-05
      • 1970-01-01
      • 2019-08-01
      • 1970-01-01
      • 2020-02-25
      • 1970-01-01
      • 2023-03-10
      • 2016-09-02
      • 2017-08-30
      相关资源
      最近更新 更多