简体   繁体   English

反应客户端componentDidMount不能正常工作(服务器端渲染)

[英]React client side componentDidMount not working properly (server side rendering)

Hello Stackoverflow community 你好Stackoverflow社区

sorry in advance if my explanation is not clear enough 如果我的解释不够清楚,请提前抱歉

when a user types a url directly. 当用户直接输入网址时。 the server makes a request, fetch the corresponding data and renders to screen. 服务器发出请求,获取相应的数据并呈现到屏幕。 and this works perfectly 这完美地工作

when a user clicks on a link, the page is suppose to switch and render new component and fetch corresponding data from server via componentDidMount and save to state but for some reason the data does not appear on page 当用户单击链接时,该页面应该切换并呈现新组件,并通过componentDidMount从服务器获取相应数据并保存到状态,但由于某种原因该数据未显示在页面上

when i run the code below, console.log('2') comes before console.log('1') meaning that state is first rendered undefined before populated with fetched data 当我运行下面的代码时,console.log('2')出现在console.log('1')之前,这意味着在填充获取的数据之前,首先将状态呈现为未定义

it looks like a async problem but i dont know my way around it and this should not be the case because it works on normal client side applications 它看起来像是一个异步问题,但我不知道解决该问题的方法,但事实并非如此,因为它适用于普通客户端应用程序

but even though the order of events is distorted the app should re-render when state change which does not happen. 但是即使事件的顺序发生了扭曲,当状态更改没有发生时,应用也应该重新渲染。

News.js 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 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>
    );
  }
}

thanks in advance for your help 在此先感谢您的帮助

You code looks fine. 您的代码看起来不错。 The following is happening: 正在发生以下情况:

In componentDidMount you request initial data. componentDidMount您请求初始数据。 This is async operation meaning that componentDidMount will finish without waiting for it to complete and console.log('2 ' + this.state) will be executed, and after that initial render will be called without any data present. 这是一个异步操作,这意味着componentDidMount将在不等待其完成的情况下完成,并且console.log('2 ' + this.state)将被执行,并且在此初始呈现之后将被调用,而没有任何数据。

Then requestInitialData gets completed and you see console.log('1 ' + data) logged. 然后requestInitialData完成,并且您看到console.log('1 ' + data)记录。 After that you update state (note that setState is also async) and News gets rendered again with data. 之后,您更新状态(请注意setState也是异步的),并且News将再次使用数据呈现。

The reason for ui not being updated could be that NewsList implement shouldComponentUpdate and do not re-render itself upon some conditions. ui未被更新的原因可能是NewsList工具应执行shouldComponentUpdate并且在某些情况下不会重新呈现自身。

I would suggest put logging inside render methods for both News and NewsList and see how they get called. 我建议将日志记录在NewsNewsList render方法中,看看它们如何被调用。 And that you do fetch data from requestInitialData method. 并且您确实从requestInitialData方法获取数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM