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 调用的主要内容,如果未能解决你的问题,请参考以下文章
Philips Hue REST api/nupnp:答案是空的