组件是否不会在状态更改时重新呈现?

时间:2019-02-08 20:00:26

标签: javascript reactjs axios

无论何时调用setState(),组件似乎都不会重新呈现。正如您从我的评论中看到的那样,状态实际上确实发生了变化,并且渲染似乎再次被调用,但是如果我不添加该if语句,而只是添加一个显示数据的段落标记,则会给我一个错误。我确定我缺少一些简单的东西,但是可以提供任何帮助。

import React from "react";
import axios from "axios";
import { constants } from "../constants/constants";
const { baseURL, apiKey, userName } = constants;

class User extends React.Component {
  constructor(props) {
  super(props);
  this.state = {
    user: []
  };
}
componentDidMount() {
  let getUserInfo = axios.create({
    baseURL,
    url: `? 
    method=user.getinfo&user=${userName}&api_key=${apiKey}&format=json`
   });
  getUserInfo().then(response => {
  let data = response.data;
  console.log(data.user.playcount); //logs second, displays correct
  this.setState(state => ({
    user: data
  }));
});
}

render() {
  console.log(this.state); //logs first and third, doesn't work on first but does on third
  let toReturn;
  if (this.state.user.length > 0) {
    toReturn = <p>{this.state.user.user.playcount}</p>;
  } else {
    toReturn = <p>didn't work</p>;
  }
  return <div>{toReturn}</div>;
  }
}

export default User;

2 个答案:

答案 0 :(得分:2)

React LifeCycle函数序列为Constructor,然后调用render方法。 在构造方法中,它初始化当前为空用户数组的状态。 现在它调用render()方法,因为this.state.user是一个空数组,引用其中的内容会产生错误

this.state.user.user.playcount

如果您没有if条件,这将产生一个错误。 在第一个渲染之后,它将调用componentDidMount,现在您获取一些更新状态。发生setState时,将再次调用render。现在,您在this.state.user中有了一些东西,然后显示就会发生。

this.state.user.length > 0 is true

看看这个:https://reactjs.org/docs/react-component.htmlhttps://reactjs.org/docs/conditional-rendering.html

您可以使用这样的条件渲染直接在单个

标签中

<p>{this.state.user.length ? this.state.user.user.playcount : 'loading'}

希望这会有所帮助。

答案 1 :(得分:0)

我认为您的问题可能与user值的形状变化有关。您将值初始化为一个空数组,但是在提取完成之后,您假设它是一个对象(通过使用user.user)。

也许您可以简化一下代码,使其看起来更像下面的代码?

/* imports */

class User extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      user: null // Make it explicit there's no value at the beginning.
    };
  }

  componentDidMount() {
    let getUserInfo = axios.create(/* ... */);
    getUserInfo().then(response => {
      let data = response.data;
      this.setState({ // No need to for a setter function as you dno't rely on the previous state's value.
        user: data.user // Assign the user object as the new value.
      });
    });
  }

  render() {
    let toReturn;
    // Since it's now a `null`, you can use a simple existence check.
    if (this.state.user) {
      // User is now an object, so you can safely refer to its properties.
      toReturn = <p>{this.state.user.playcount}</p>;
    } else {
      toReturn = <p>No data yet.</p>;
    }
    return <div>{toReturn}</div>;
  }
}

export default User;