<commit_before>import React from 'react';
import isEqual from 'lodash/lang/isEqual';

import BaseComponent from '../components/BaseComponent';
import TrackingPixel from '../../lib/TrackingPixel';
import constants from '../../constants';

class BasePage extends BaseComponent {
  static propTypes = {
    ctx: React.PropTypes.object.isRequired,
    data: React.PropTypes.object.isRequired,
    app: React.PropTypes.object.isRequired,
  };
  
  constructor (props) {
    super(props);

    this.props = props;

    this.state = {
      data: {},
      meta: {},
      loaded: !!props.dataCache,
      finished: false,
    };

    if (props.dataCache) {
      for (var k in props.dataCache) {
        props.data.set(k, Promise.resolve(props.dataCache[k]));

        if (props.dataCache[k] && props.dataCache[k].body) {
          this.state.data[k] = props.dataCache[k].body;
          this.state.meta[k] = props.dataCache[k].headers;

          if (this.state.meta[k].tracking && this.track === k) {
            this.fireTrackingPixel(this.state.meta[k].tracking);
          }
        } else {
          this.state.data[k] = props.dataCache[k];

          if (k === 'subreddit') {
            props.app.emit(constants.SET_META_COLOR,
              props.dataCache[k].key_color || constants.DEFAULT_KEY_COLOR);
          }
        }
      }
    }

    this.watchProperties();
  } 

  watchProperties() {
    // Handle no-data error-page case
    if (this.props.data) {
      for (var key of this.props.data.keys()) {
        if (!this.props.dataCache[key]) {
          this.watch(key);
        }
      }

      if (isEqual([...this.props.data.keys()].sort(), Object.keys(this.props.dataCache).sort())) {
        this.finish();
      }
    }
  }

  watch (property) {
    this.props.data.get(property).then((p) => {
      let data;
      if (p.body) {
        data = Object.assign({}, this.state.data);
        var meta = Object.assign({}, this.state.meta);

        data[property] = p.body;
        meta[property] = p.headers;

        if (p.headers.tracking && this.track === property) {
          this.fireTrackingPixel(p.headers.tracking);
        }

        this.setState({
          data,
          meta,
        });

        if (property === 'preferences') {
          this.props.app.emit(constants.TOGGLE_OVER_18, p.body.over_18);
        }
      } else {
        data = Object.assign({}, this.state.data);

        data[property] = p;

        if (property === 'subreddit') {
          this.props.app.emit(constants.SET_META_COLOR, p.key_color || constants.DEFAULT_KEY_COLOR);
        }

        this.setState({
          data,
        });
      }

      if (isEqual([...this.props.data.keys()].sort(), Object.keys(this.state.data).sort())) {
        this.finish();
      }
    }, (e) => {
      this.props.app.error(e, this.props.ctx, this.props.app);
      this.props.app.forceRender(this.props.ctx.body, this.props);
    });
  }

  finish () {
    if (this.state.finished === false && this.track) {
      this.props.app.emit('pageview', { ...this.props, data: this.state.data });
      this.setState({ finished: true });<commit_msg>Only run `finish` setstate on the client<commit_after>import React from 'react';
import isEqual from 'lodash/lang/isEqual';

import BaseComponent from '../components/BaseComponent';
import TrackingPixel from '../../lib/TrackingPixel';
import constants from '../../constants';

class BasePage extends BaseComponent {
  static propTypes = {
    ctx: React.PropTypes.object.isRequired,
    data: React.PropTypes.object.isRequired,
    app: React.PropTypes.object.isRequired,
  };
  
  constructor (props) {
    super(props);

    this.props = props;

    this.state = {
      data: {},
      meta: {},
      loaded: !!props.dataCache,
      finished: false,
    };

    if (props.dataCache) {
      for (var k in props.dataCache) {
        props.data.set(k, Promise.resolve(props.dataCache[k]));

        if (props.dataCache[k] && props.dataCache[k].body) {
          this.state.data[k] = props.dataCache[k].body;
          this.state.meta[k] = props.dataCache[k].headers;

          if (this.state.meta[k].tracking && this.track === k) {
            this.fireTrackingPixel(this.state.meta[k].tracking);
          }
        } else {
          this.state.data[k] = props.dataCache[k];

          if (k === 'subreddit') {
            props.app.emit(constants.SET_META_COLOR,
              props.dataCache[k].key_color || constants.DEFAULT_KEY_COLOR);
          }
        }
      }
    }

    this.watchProperties();
  } 

  watchProperties() {
    // Handle no-data error-page case
    if (this.props.data) {
      for (var key of this.props.data.keys()) {
        if (!this.props.dataCache[key]) {
          this.watch(key);
        }
      }

      if (isEqual([...this.props.data.keys()].sort(), Object.keys(this.props.dataCache).sort())) {
        this.finish();
      }
    }
  }

  watch (property) {
    this.props.data.get(property).then((p) => {
      let data;
      if (p.body) {
        data = Object.assign({}, this.state.data);
        var meta = Object.assign({}, this.state.meta);

        data[property] = p.body;
        meta[property] = p.headers;

        if (p.headers.tracking && this.track === property) {
          this.fireTrackingPixel(p.headers.tracking);
        }

        this.setState({
          data,
          meta,
        });

        if (property === 'preferences') {
          this.props.app.emit(constants.TOGGLE_OVER_18, p.body.over_18);
        }
      } else {
        data = Object.assign({}, this.state.data);

        data[property] = p;

        if (property === 'subreddit') {
          this.props.app.emit(constants.SET_META_COLOR, p.key_color || constants.DEFAULT_KEY_COLOR);
        }

        this.setState({
          data,
        });
      }

      if (isEqual([...this.props.data.keys()].sort(), Object.keys(this.state.data).sort())) {
        this.finish();
      }
    }, (e) => {
      this.props.app.error(e, this.props.ctx, this.props.app);
      this.props.app.forceRender(this.props.ctx.body, this.props);
    });
  }

  finish () {
    if (this.props.ctx.env !== 'SERVER') {
      if (this.state.finished === false && this.track) {
        this.props.app.emit('pageview', {
          ...this.props,
          data: this.state.data,
        });
        this.setState({ finished: true });
      }
{'fraction_non_alphanumeric': 0.1644500078235018, 'fraction_numerical': 0.0012517602879048662, 'mean_word_length': 2.0730769230769233, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5873376', 'n_tokens_mistral': 2056, 'n_tokens_neox': 2021, 'n_words': 331}