如何在组件挂载之前获取数据?

时间:2020-01-13 20:08:54

标签: javascript reactjs typescript

我正在尝试从Node中的本地服务器获取数据,但是我的问题是,当我调用组件的render函数时,来自该状态的数组用户似乎为空,因此不会在该状态下渲染用户。如我所愿,在屏幕上,奇怪的是,我在抓取中拥有的console.log(users)确实为我带来了数据,但是当我在渲染器上进行处理时却没有给我带来什么:

这是到目前为止的代码:

import React, { PureComponent } from "react";
import Nav from "./Nav";
import { IState, IProps } from "./Interfaces";

class Home extends PureComponent<IProps, IState> {
  constructor(props: IProps) {
    super(props);

    this.state = {
      users: [],
      books: []
    };
  }

  getUsers = async () => {
    const response = await fetch(`http://localhost:5000/users`, {
      headers: {
        "Content-Type": "application/json"
      }
    });
    const users = await response.json();
    for (let user of users) {
      this.state.users.push(user);
    }
    console.log(this.state.users);
  };

  getBooks = async (id: number) => {
    const token =
      "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlciI6Implc3VzIiwiaXNBZG1pbiI6dHJ1ZSwiaWF0IjoxNTc2NjgzNTkwfQ.1FWmtj-fCsqSza_pwfewIpp3zQ50BxDagRTvrh5x3cU";
    const response = await fetch(`http://localhost:5000/bookUser/${id}/books`, {
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "application/json"
      }
    });
    const books = await response.json();
    this.setState({ books });
  };

  onUserSelection = (id: number) => this.getBooks(id);

  componentDidlMount() {
    this.getUsers();
  }

  render() {
    const { users } = this.state;
    console.log(this.state.users);
    return (
      <div>
        <Nav username={this.props.username} />
        <h1>Hello {this.props.username}</h1>
        <table>
          <tbody>
            <tr>
              <th>ID</th>
              <th>Name</th>
            </tr>
            {users.map(u => (
              <tr
                key={u.user_id}
                onClick={() => this.onUserSelection(u.user_id)}
              >
                <td>{u.user_id}</td>
                {console.log(u.user_id)}
                <td>{u.username}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    );
  }
}

export default Home;

2 个答案:

答案 0 :(得分:1)

如Sameer的注释中先前提到的,您希望避免在设置状态时使用push。这样做不会触发重新渲染。

使用以下内容代替您的this.state.users.push(user)

this.setState(prevState => ({
  users: [...prevState.users, user]
}, console.log("updated users", this.state.users)));

这里有些不同。

setState中的第一个参数接受一个函数。该函数中有一个自变量,它是您的先前状态(prevState)。使用散布运算符,您可以创建包含旧用户和所有新用户的新数组。

第二,由于setState的异步特性,您不能期望在setState函数之后立即运行console.log()。相反,您可以传递一个回调函数(在此实例中为console.log)作为setState的第二个参数,并在完成后将其触发。

答案 1 :(得分:0)

使用setState填充处于状态的用户

this.setState({
users: users
})

在地图之前的渲染中,执行此操作

{
    users.length>0 &&
    users.map(u => ( <tr key={u.user_id} onClick={() => this.onUserSelection(u.user_id)} > <td>{u.user_id}</td> {console.log(u.user_id)} <td>{u.username}</td> </tr> ))
}