geelen/react-snapshot

Component doesn't rerender on props change

alexandr2110pro opened this issue · 5 comments

Hi. Sorry if it is a duplicate but here is the issue:

AppRoot Component:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';

import {
  getModelData,
  isContentsConfigLoaded,
} from '../lib/services/reducers';

import {
  requestEntities,
  loadContentsConfig,
  preloadLargeContentData,
} from '../lib/services/actions/actions';

import { DialogModel, TranslationsTableModel } from '../lib/models';
import { DialogsStack } from './DialogsStack';
import { Location } from '../components/Location/Location';

import './webflow-overrides.css';

const mapStateToProps = (state, props) => ({
  dialogsStack: getModelData(state, DialogModel, 'all'),
  configReady: isContentsConfigLoaded(state),
});

const mapDispatchToProps = {
  requestEntities,
  loadContentsConfig,
  preloadLargeContentData,
};


@connect(mapStateToProps, mapDispatchToProps)
export class AppRoot extends Component {

  static propTypes = {
    requestEntities: PropTypes.func.isRequired,
    configReady: PropTypes.bool.isRequired,
    dialogsStack: PropTypes.arrayOf(PropTypes.object),
    loadContentsConfig: PropTypes.func.isRequired,
    preloadLargeContentData: PropTypes.func.isRequired,
  };

  componentWillMount() {
    this.props.requestEntities(DialogModel, 'all');
    this.props.requestEntities(TranslationsTableModel, 'all');
    this.props.loadContentsConfig();
  }

  componentWillReceiveProps(nextProps, nextContext) {
    console.warn('AppRoot componentWillReceiveProps');
    if (nextProps.configReady && !this.state.preloadingStarted) this._startPreloadingData();
  }

  state = { preloadingStarted: false }

  render() {
    const { dialogsStack } = this.props;
    console.warn('render!', dialogsStack);

    return (
      <div className="app-root">
        <Location />
        {
          dialogsStack && dialogsStack.length
            ? <DialogsStack dialogsStack={dialogsStack} />
            : <div>Loading</div>
        }
      </div>
    );
  }

  _startPreloadingData() {
    const { preloadLargeContentData } = this.props;
    this.setState({ preloadingStarted: true });
    preloadLargeContentData();
  }
}

here is the console from the browser:
screenshot 2017-12-16 22 29 50

(I have a bunch of other debugging console.warn in other parts as you can see. They are just displaying the request was successful so that the Redux store would update as expected.)


But when I run the react-snapshot, here is what I'm getting:

screenshot 2017-12-16 22 36 38

As you see, the render is called only once, and the componentWillReceiveProps has not been called at all.

So it always renders the following as the snapshot:

    <div class="app-root">
      <div>Loading</div>
    </div>

This happens because current version can't "wait" for requests to finish. It supposed to be fixed in API v2 #30

I suppose the same happens with the google crawler bot.

@stereobooster do you have any information on when it will be merged?

It is not finished. No information on when it will be merged

API v2 alone can be not sufficient for your case. Assume pre-renderer waited long enough, to render all HTML. On the client side browser receives all HTML, React application starts to execute, its state is empty, React erases prerendered HTML and places "Loading" starts to do AJAX request to get data. What you can do is:

  • use Redux and this feature #46
  • use some mechanism to store AJAX to window at prerender time

If you would use async components, you would need to store a state of loaded components too. For example like in loadable-components