Hello Stackoverflow社区
如果我的解释不够明确,请提前抱歉当用户直接输入网址时。服务器发出请求,获取相应的数据并呈现屏幕。这完美地运作
当用户点击某个链接时,该页面会假设切换并呈现新组件,并通过componentDidMount从服务器获取相应的数据并保存到状态但由于某种原因,数据不会显示在页面上
当我运行下面的代码时,console.log('2')出现在console.log('1')之前,这意味着在填充获取的数据之前,状态首先呈现为未定义
它看起来像一个异步问题,但我不知道我的方式,这不应该是这种情况,因为它适用于普通的客户端应用程序
但即使事件的顺序失真,应用程序也应该在状态发生变化时重新呈现。
News.js
import React from 'react';
import NewsList from './newslist';
import 'es6-promise'
import 'isomorphic-fetch';
class News extends React.Component {
constructor(props){
super(props)
let initialData;
if(props.staticContext){
initialData = props.staticContext.initialData
} else if (typeof window !== 'undefined') {
initialData = window.__initialData__
delete window.__initialData__
}
this.state = {news: initialData }
}
componentDidMount() {
News.requestInitialData().then(data => {
console.log('1 ' + data) <------- console log 1
return this.setState({ news: data })
});
console.log('2 ' + this.state) <------- console log 2
}
static requestInitialData() {
return fetch('http://localhost:3000/api/data')
.then(response => response.json())
.catch(err => console.log(err))
}
render() {
return (
<div className="App">
<NewsList news={this.state.news} />
</div>
);
}
}
module.exports = News
NewsList.js
import React, { Component } from "react";
export default class NewsList extends Component {
constructor(props){
super(props)
// const data = (this.props.news) ? this.props.news : '';
this.state = {news : this.props.news,
sortOrder: 'ascending'}
}
sortOrder(order, event) {
event.preventDefault();
const data = Object.assign([], this.state.news)
let data2;
if (order === 'ascending') {
data.sort( (a,b) => a.id - b.id )
data2 = 'ascending'
}
else if (order === 'descending') {
data.sort( (a,b) => b.id - a.id )
data2 = 'descending'
}
this.setState({
news: data,
sortOrder: data2
});
}
render() {
const news = this.state.news
return (
<div>
<div className="sort">
<a
href="#"
className={"ascending"}
onClick={this.sortOrder.bind(this, "ascending")}>
Ascending
</a>|
<a
href="#"
className={"descending"}
onClick={this.sortOrder.bind(this, "descending")}>
Date
</a>
</div>
{news && news.map(post =>
<div key={post.id} className="news-item">
<p>
<span className="news-position">{post.id}. ▲</span> {post.title}{" "}
<small>(by {post.author})</small>
</p>
<small className="news-details">
{post.upvotes} upvotes
</small>
</div>
)}
</div>
);
}
}
提前感谢您的帮助
答案 0 :(得分:0)
你的代码看起来很好。发生以下情况:
在componentDidMount
中,您需要初始数据。这是异步操作,意味着componentDidMount
将在不等待它完成的情况下完成,并且console.log('2 ' + this.state)
将被执行,之后将调用初始渲染而不存在任何数据。
然后requestInitialData
完成,您会看到console.log('1 ' + data)
已登录。之后,您更新状态(请注意,setState也是异步的),然后使用数据再次呈现新闻。
ui未被更新的原因可能是NewsList实现shouldComponentUpdate并且在某些条件下不会重新呈现。
我建议将记录放在News
和NewsList
的渲染方法中,看看它们是如何被调用的。并且您确实从requestInitialData
方法获取数据。