Render() 状态元素最初是空的,直到 api 调用

Posted

技术标签:

【中文标题】Render() 状态元素最初是空的,直到 api 调用【英文标题】:Render() state element is initially empty until api call 【发布时间】:2021-06-25 06:11:18 【问题描述】:

我有一个类组件,它应该在 API 调用后显示一些列表值,在我的渲染函数中,我调用一个函数来填充一些其他状态列表(使用获取的列表中的特定对象属性),问题是在render 调用,状态值最初是空的,因此我返回的组件也只是空的。

我尝试过使用 componentDidUpdate(),但我不知道如何使用它,它通常会给我一个无限循环。

这是我的相关代码:


class AdminSales extends React.Component 
  constructor(props) 
    super(props);

    this.state = 
      items: [],
      data: [],
    ;
  

  componentDidMount() 
    this.fetchData();
  

  fetchData() 
    fetch("/api/items")
      .then((res) => res.json())
      .then((items) => this.setState( items: items ));
  

  componentDidUpdate(prevState) 
    if (JSON.stringify(prevState.items) == JSON.stringify(this.state.items)) 
      // Do nothing 
     else 
      // This gives infinite loop ...
      // this.fetchData();
    

  

  populateData() 
    this.state.items.forEach(function (item) 
      this.state.data.push(
        name: item.name,
        value: item.quantity,
      );
    , this);
  

  render() 
    // Output shown line: 65
    console.log(this.state);
    this.populateData();
    const  data  = this.state;
    return ( ... );
  


export default AdminSales;

任何帮助将不胜感激。

【问题讨论】:

除了render 中明显的状态突变和副作用之外,将items 状态复制到data 状态有什么意义?似乎很没有意义。 React 组件状态应该是表示您的数据所需的最小数据量,您应该避免重复。除非您使用非空数组定义状态,否则它们将在初始渲染周期中始终为空。如果这是一个问题,那么应用一些条件渲染,直到获取的数据填充到状态。 是的,我太傻了,我试图格式化它,但后来意识到我可以在 fetch 请求中做到这一点。 【参考方案1】:

首先,您的代码中存在多个问题

render 中的更新/变异状态 不是使用setState 更新状态,而是在populateData 方法中就地更新状态

另外,正如@Drew 所提到的,我们不必将items 复制到data 中,而是可以在从API 获得响应后只将所需的信息存储在状态中。

在等待响应的同时,如果您想显示加载信息,您也可以这样做。

以下是涵盖上述所有要点的示例。

const mockAPI = () => 
  return new Promise((resolve) => setTimeout(() => 
    resolve([id:1, name: "ABC", quantity: 1, id: 2, name: "DEF", quantity: 5, id: 3, name: "XYZ", quantity: 9])
  , 500));


class AdminSales extends React.Component 
  constructor(props) 
    super(props);

    this.state = 
      items: [],
      loading: true
    ;
  

  componentDidMount() 
    this.fetchData();
  

  fetchData = () => 
    mockAPI()
      .then((res) => 
        this.populateData(res);
      );
  

  populateData = (data) => 
    this.setState( 
      items: data.map((name, quantity) => (
        name,
        value: quantity
      )),
      loading: false
    )
  

  render() 
    //console.log(this.state);
    const  items, loading  = this.state;
    return loading ? <p>Loading...</p> : 
    items.map(item => (
      <div>item.name: item.value</div>
    ));
  



ReactDOM.render(<AdminSales />, document.getElementById("react"));
<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>

<div id="react"></div>

注意:为简单起见,我使用简单的setTimeout 模拟了后端 API。

【讨论】:

是的,现在可以使用了!非常感谢详细解答! :) 很高兴为您提供帮助 :-)

以上是关于Render() 状态元素最初是空的,直到 api 调用的主要内容,如果未能解决你的问题,请参考以下文章

10_阻塞队列

Java阻塞队列的实现

java阻塞队列得实现

Philips Hue REST api/nupnp:答案是空的

在 TableViewController 上添加图像直到搜索栏处于非活动状态

25Java并发性和多线程-阻塞队列