Skip to content
Merged
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,10 @@
All notable changes to `dash` will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Changed
- [#1145](https://github.com/plotly/dash/pull/1145) Update from React 16.8.6 to 16.13.0

## [1.9.1] - 2020-02-27
### Added
- [#1133](github.com/plotly/dash/pull/1133) Allow the `compress` config variable to be set with an environment variable with DASH_COMPRESS=FALSE
Expand Down
3 changes: 2 additions & 1 deletion dash-renderer/.eslintrc.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -102,6 +102,7 @@
"no-new-wrappers": ["error"],
"no-param-reassign": ["error"],
"no-process-env": ["warn"],
"no-prototype-builtins": ["off"],

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

myObject.hasOwnProperty(...) is fine

"no-proto": ["error"],
"no-redeclare": ["error"],
"no-return-assign": ["error"],
Expand DownExpand Up@@ -141,7 +142,7 @@
}],
"no-magic-numbers": ["error", {
"ignoreArrayIndexes": true,
"ignore": [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 100, 10, 16, 0.5, 25]
"ignore": [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 100, 10, 16, 0.5, 25, 200, 500]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some xhr return codes

}],
"no-underscore-dangle": ["off"],
"no-useless-escape": ["off"]
Expand Down
9,291 changes: 6,497 additions & 2,794 deletions dash-renderer/package-lock.json

Large diffs are not rendered by default.

76 changes: 38 additions & 38 deletions dash-renderer/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,48 +20,48 @@
"author": "chriddyp",
"license": "MIT",
"dependencies": {
"react": "16.8.6",
"react-dom": "16.8.6",
"@babel/polyfill": "7.8.7",
"cookie": "^0.4.0",
"dependency-graph": "^0.9.0",
"prop-types": "15.7.2",
"cookie": "^0.3.1",
"dependency-graph": "^0.5.0",
"radium": "^0.22.1",
"ramda": "^0.26.1",
"react-redux": "^4.4.5",
"redux": "^3.4.0",
"redux-actions": "^0.9.1",
"redux-thunk": "^2.0.1",
"viz.js": "1.8.0"
"radium": "^0.26.0",
"ramda": "^0.27.0",
"react": "16.13.0",
"react-dom": "16.13.0",
"react-redux": "^7.2.0",
"redux": "^4.0.5",
"redux-actions": "^2.6.5",
"redux-thunk": "^2.3.0",
"viz.js": "2.1.2"
},
"devDependencies": {
"@babel/core": "^7.6.0",
"@babel/plugin-transform-modules-commonjs": "^7.6.0",
"@babel/polyfill": "7.7.0",
"@babel/preset-env": "^7.6.0",
"@babel/preset-react": "^7.0.0",
"@plotly/dash-component-plugins": "^1.0.2",
"@svgr/webpack": "^4.1.0",
"babel-eslint": "^10.0.3",
"@babel/core": "^7.8.7",
"@babel/plugin-transform-modules-commonjs": "^7.8.3",
"@babel/preset-env": "^7.8.7",
"@babel/preset-react": "^7.8.3",
"@plotly/dash-component-plugins": "^1.2.0",
"@svgr/webpack": "^5.2.0",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.0.6",
"css-loader": "^3.2.0",
"es-check": "^5.0.0",
"eslint": "^5.15.3",
"eslint-config-airbnb": "^17.1.0",
"eslint-config-prettier": "^3.6.0",
"eslint-plugin-import": "^2.16.0",
"eslint-plugin-jsx-a11y": "^6.2.1",
"eslint-plugin-prettier": "^3.0.1",
"eslint-plugin-react": "^7.12.4",
"jest": "^24.9.0",
"prettier": "^1.16.4",
"prettier-eslint": "^8.8.2",
"prettier-eslint-cli": "^4.7.1",
"css-loader": "^3.4.2",
"es-check": "^5.1.0",
"eslint": "^6.8.0",
"eslint-config-airbnb": "^18.0.1",
"eslint-config-prettier": "^6.10.0",
"eslint-plugin-import": "^2.20.1",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-prettier": "^3.1.2",
"eslint-plugin-react": "^7.18.3",
"jest": "^25.1.0",
"prettier": "^1.19.1",
"prettier-eslint": "^9.0.1",
"prettier-eslint-cli": "^5.0.0",
"prettier-stylelint": "^0.4.2",
"style-loader": "^1.0.0",
"webpack": "^4.39.3",
"webpack-cli": "^3.3.8",
"webpack-dev-server": "^3.1.11",
"webpack-serve": "^3.1.1",
"whatwg-fetch": "^2.0.2"
"style-loader": "^1.1.3",
"webpack": "^4.42.0",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.10.3",
"webpack-serve": "^3.2.0",
"whatwg-fetch": "^3.0.0"
}
}
110 changes: 45 additions & 65 deletions dash-renderer/src/APIController.react.js
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
import {connect} from 'react-redux';
import {includes, isEmpty, isNil} from 'ramda';
import React, {Component} from 'react';
import React, {useEffect, useState} from 'react';
import PropTypes from 'prop-types';
import TreeContainer from './TreeContainer';
import GlobalErrorContainer from './components/error/GlobalErrorContainer.react';
Expand All@@ -17,24 +17,13 @@ import {STATUS} from './constants/constants';

/**
* Fire off API calls for initialization
* @param {*} props props
* @returns {*} component
*/
class UnconnectedContainer extends Component {
constructor(props) {
super(props);
this.initialization = this.initialization.bind(this);
this.state = {
errorLoading: false,
};
}
componentDidMount() {
this.initialization(this.props);
}

componentWillReceiveProps(props) {
this.initialization(props);
}
const UnconnectedContainer = props => {
const [errorLoading, setErrorLoading] = useState(false);

initialization(props) {
useEffect(() => {

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rewriting the ApiController as a functional component allows the use of useEffect which covers didMount / didUpdate lifecycle events. willReceiveProps is now also covered by it because the two first lifecycle methods already cover the same grounds, if slightly differently.

const {
appLifecycle,
dependenciesRequest,
Expand DownExpand Up@@ -81,74 +70,65 @@ class UnconnectedContainer extends Component {
// Hasn't already hydrated
appLifecycle === getAppState('STARTED')
) {
let errorLoading = false;
let error = false;
try {
dispatch(hydrateInitialOutputs());
} catch (err) {
errorLoading = true;
error = true;
} finally {
this.setState(state =>
state.errorLoading !== errorLoading ? {errorLoading} : null
);
setErrorLoading(error);
}
}
}
});

render() {
const {
appLifecycle,
dependenciesRequest,
layoutRequest,
layout,
config,
} = this.props;

const {errorLoading} = this.state;
const {
appLifecycle,
dependenciesRequest,
layoutRequest,
layout,
config,
} = props;

if (
layoutRequest.status &&
!includes(layoutRequest.status, [STATUS.OK, 'loading'])
) {
return <div className="_dash-error">Error loading layout</div>;
} else if (
errorLoading ||
(dependenciesRequest.status &&
!includes(dependenciesRequest.status, [STATUS.OK, 'loading']))
) {
return (
<div className="_dash-error">Error loading dependencies</div>
);
} else if (
appLifecycle === getAppState('HYDRATED') &&
config.ui === true
) {
return (
<GlobalErrorContainer>
<TreeContainer
_dashprivate_layout={layout}
_dashprivate_path={[]}
/>
</GlobalErrorContainer>
);
} else if (appLifecycle === getAppState('HYDRATED')) {
return (
if (
layoutRequest.status &&
!includes(layoutRequest.status, [STATUS.OK, 'loading'])
) {
return <div className="_dash-error">Error loading layout</div>;
} else if (
errorLoading ||
(dependenciesRequest.status &&
!includes(dependenciesRequest.status, [STATUS.OK, 'loading']))
) {
return <div className="_dash-error">Error loading dependencies</div>;
} else if (appLifecycle === getAppState('HYDRATED') && config.ui === true) {
return (
<GlobalErrorContainer>
<TreeContainer
_dashprivate_layout={layout}
_dashprivate_path={[]}
/>
);
}

return <div className="_dash-loading">Loading...</div>;
</GlobalErrorContainer>
);
} else if (appLifecycle === getAppState('HYDRATED')) {
return (
<TreeContainer
_dashprivate_layout={layout}
_dashprivate_path={[]}
/>
);
}
}

return <div className="_dash-loading">Loading...</div>;
};

UnconnectedContainer.propTypes = {
appLifecycle: PropTypes.oneOf([
getAppState('STARTED'),
getAppState('HYDRATED'),
]),
dispatch: PropTypes.func,
dependenciesRequest: PropTypes.object,
graphs: PropTypes.object,
layoutRequest: PropTypes.object,
layout: PropTypes.object,
paths: PropTypes.object,
Expand Down
2 changes: 0 additions & 2 deletions dash-renderer/src/AccessDenied.react.js
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
/* global window:true, document:true */
import React from 'react';
import {mergeRight, once} from 'ramda';
import PropTypes from 'prop-types';
Expand DownExpand Up@@ -31,7 +30,6 @@ function AccessDenied(props) {
<a
style={styles.base.a}
onClick={() => {
/* eslint no-empty: ["error", { "allowEmptyCatch": true }] */
try {
document.cookie =
`${constants.OAUTH_COOKIE_NAME}=; ` +
Expand Down
3 changes: 1 addition & 2 deletions dash-renderer/src/AppContainer.react.js
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
/* global document:true */
import {connect} from 'react-redux';
import React from 'react';
import PropTypes from 'prop-types';
Expand All@@ -21,7 +20,7 @@ class UnconnectedAppContainer extends React.Component {
}
}

componentWillMount() {
UNSAFE_componentWillMount() {
const {dispatch} = this.props;
const config = JSON.parse(
document.getElementById('_dash-config').textContent
Expand Down
4 changes: 0 additions & 4 deletions dash-renderer/src/DashRenderer.js
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
/* eslint-env browser */

'use strict';

import React from 'react';
import ReactDOM from 'react-dom';
import AppProvider from './AppProvider.react';
Expand Down
1 change: 0 additions & 1 deletion dash-renderer/src/actions/api.js
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
/* global fetch: true */
import {mergeDeepRight} from 'ramda';
import {handleAsyncError, getCSRFHeader} from '../actions';
import {urlBase} from '../utils';
Expand Down
15 changes: 5 additions & 10 deletions dash-renderer/src/actions/index.js
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
/* global fetch:true, Promise:true, document:true */
import {
adjust,
any,
Expand DownExpand Up@@ -429,9 +428,8 @@ export function notifyObservers(payload) {
);
}

/* eslint-disable consistent-return */
/* eslint-disable-next-line consistent-return */
return Promise.all(promises);
/* eslint-enable consistent-return */
};
}

Expand DownExpand Up@@ -645,13 +643,13 @@ function updateOutput(
return;
}

/* eslint-disable no-console */
/* eslint-disable-next-line no-console */
console.error(
`The following error occurred while executing ${clientside_function.namespace}.${clientside_function.function_name} ` +
`in order to update component "${payload.output}" ⋁⋁⋁`
);
/* eslint-disable-next-line no-console */
console.error(e);
/* eslint-enable no-console */

/*
* Update the request queue by treating an unsuccessful clientside
Expand All@@ -665,15 +663,14 @@ function updateOutput(

// Returning promises isn't support atm
if (type(returnValue) === 'Promise') {
/* eslint-disable no-console */
/* eslint-disable-next-line no-console */
console.error(
'The clientside function ' +
`${clientside_function.namespace}.${clientside_function.function_name} ` +
'returned a Promise instead of a value. Promises are not ' +
'supported in Dash clientside right now, but may be in the ' +
'future.'
);
/* eslint-enable no-console */
updateRequestQueue(true, STATUS.CLIENTSIDE_ERROR);
return;
}
Expand DownExpand Up@@ -736,12 +733,10 @@ function updateOutput(
hooks.request_pre(payload);
}

/* eslint-disable consistent-return */
/* eslint-disable-next-line consistent-return */
return fetch(
`${urlBase(config)}_dash-update-component`,
mergeDeepRight(config.fetch, {
/* eslint-enable consistent-return */

method: 'POST',
headers: getCSRFHeader(),
body: JSON.stringify(payload),
Expand Down
4 changes: 1 addition & 3 deletions dash-renderer/src/components/core/DocumentTitle.react.js
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
/* global document:true */

import {connect} from 'react-redux';
import {any} from 'ramda';
import {Component} from 'react';
Expand All@@ -13,7 +11,7 @@ class DocumentTitle extends Component {
};
}

componentWillReceiveProps(props) {
UNSAFE_componentWillReceiveProps(props) {
if (any(r => r.status === 'loading', props.requestQueue)) {
document.title = 'Updating...';
} else {
Expand Down
1 change: 0 additions & 1 deletion dash-renderer/src/components/core/Reloader.react.js
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
/* eslint-disable no-undef,react/no-did-update-set-state,no-magic-numbers */
import {
comparator,
equals,
Expand Down
Loading