0

你好 Stackoverflow 社区

如果我的解释不够清楚,请提前道歉

当用户直接输入 url 时。服务器发出请求,获取相应的数据并呈现到屏幕上。这完美地工作

当用户点击一个链接时,页面应该切换和渲染新组件,并通过 componentDidMount 从服务器获取相应的数据并保存到状态,但由于某种原因数据没有出现在页面上

当我运行下面的代码时,console.log('2') 出现在 console.log('1') 之前,这意味着状态在填充获取的数据之前首先呈现为未定义

它看起来像一个异步问题,但我不知道如何解决它,这不应该是这种情况,因为它适用于普通的客户端应用程序

但是即使事件的顺序被扭曲了,当状态改变没有发生时,应用程序也应该重新渲染。

新闻.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

新闻列表.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}. ▲&lt;/span> {post.title}{" "}
                <small>(by {post.author})</small>
              </p>
              <small className="news-details">
                {post.upvotes} upvotes
              </small>
          </div>
        )}
      </div>
    );
  }
}

在此先感谢您的帮助

4

1 回答 1

0

你的代码看起来不错。以下情况正在发生:

componentDidMount您请求初始数据时。这是异步操作,意味着componentDidMount无需等待其完成即可完成并console.log('2 ' + this.state)执行,然后在不存在任何数据的情况下调用初始渲染。

然后requestInitialData完成,您会看到已console.log('1 ' + data)记录。之后,您更新状态(注意 setState 也是异步的)并且新闻再次使用数据呈现。

ui 未更新的原因可能是 NewsList 实现了 shouldComponentUpdate并且在某些情况下不重新渲染自身。

我建议将日志记录放在两者的渲染方法中NewsNewsList然后看看它们是如何被调用的。并且您确实从requestInitialData方法中获取数据。

于 2017-08-24T14:40:21.857 回答