diff --git a/CHANGELOG.md b/CHANGELOG.md index 08c995a14ab..11c865f62d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,46 @@ +## 3.3.0 (2019-xx-xx) + +DRAFT + +### Custom Templates + +DRAFT + +### Optional Chaining and Nullish Coalescing Operators + +We now support the [optional chaining](https://github.com/TC39/proposal-optional-chaining) and [nullish coalescing](https://github.com/tc39/proposal-nullish-coalescing) operators! + +```js +// Optional chaining +a?.(); // undefined if `a` is null/undefined +b?.c; // undefined if `b` is null/undefined + +// Nullish coalescing +undefined ?? 'some other default'; // result: 'some other default' +null ?? 'some other default'; // result: 'some other default' +'' ?? 'some other default'; // result: '' +0 ?? 300; // result: 0 +false ?? true; // result: false +``` + +**If your're using TypeScript, you will need to upgrade your `typescript` dependency to `3.7.0` or later if you wish to use the new operators.** + +**If you're using Visual Studio Code 1.40 (the latest as of this release) or earlier, you will need to configure your editor if you want it to understand the new operators.** + +If you're using TypeScript in your project and have already upgrade its version as described above, then you can [configure VS Code to `Use Workspace Version` of TypeScript](https://code.visualstudio.com/docs/typescript/typescript-compiling#_using-newer-typescript-versions). If your project isn't using TypeScript, you can use the [JavaScript and TypeScript Nightly extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-typescript-next) until VS Code releases a newer version including TypeScript `3.7.0` or newer. + +### Numeric Separators + +We've added support for [numeric separators](https://github.com/tc39/proposal-numeric-separator) to improve readability of numeric literals. + +```js +1000000000; // Is this a billion? a hundred millions? Ten millions? +101475938.38; // what scale is this? what power of 10? + +1_000_000_000; // Ah, so a billion +101_475_938.38; // And this is hundreds of millions +``` + ## 3.2.0 (2019-10-03) v3.2.0 is a minor release that adds support for production profiling and ignoring TypeScript type errors to make migrating JavaScript projects to TypeScript easier. It also includes other minor bug fixes and documentation updates. diff --git a/packages/react-scripts/fixtures/kitchensink/template/src/App.js b/packages/react-scripts/fixtures/kitchensink/template/src/App.js index 50fd8932341..c9d768f28df 100644 --- a/packages/react-scripts/fixtures/kitchensink/template/src/App.js +++ b/packages/react-scripts/fixtures/kitchensink/template/src/App.js @@ -171,6 +171,11 @@ class App extends Component { this.setFeature(f.default) ); break; + case 'nullish-coalescing': + import('./features/syntax/NullishCoalescing').then(f => + this.setFeature(f.default) + ); + break; case 'object-destructuring': import('./features/syntax/ObjectDestructuring').then(f => this.setFeature(f.default) @@ -181,6 +186,11 @@ class App extends Component { this.setFeature(f.default) ); break; + case 'optional-chaining': + import('./features/syntax/OptionalChaining').then(f => + this.setFeature(f.default) + ); + break; case 'promises': import('./features/syntax/Promises').then(f => this.setFeature(f.default) diff --git a/packages/react-scripts/fixtures/kitchensink/template/src/features/syntax/NullishCoalescing.js b/packages/react-scripts/fixtures/kitchensink/template/src/features/syntax/NullishCoalescing.js new file mode 100644 index 00000000000..ed5f916399c --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/template/src/features/syntax/NullishCoalescing.js @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; + +function load() { + return [ + { id: 1, name: '1' }, + { id: 2, name: '2' }, + { id: 3, name: '3' }, + { id: 4, name: '4' }, + ]; +} + +export default class extends Component { + static propTypes = { + onReady: PropTypes.func.isRequired, + }; + + constructor(props) { + super(props); + this.state = { users: [] }; + } + + async componentDidMount() { + const users = load(); + this.setState({ users }); + } + + componentDidUpdate() { + this.props.onReady(); + } + + render() { + return ( +
+ {this.state.users.map(user => ( +
{user.name ?? 'John Doe'}
+ ))} +
+ ); + } +} diff --git a/packages/react-scripts/fixtures/kitchensink/template/src/features/syntax/NullishCoalescing.test.js b/packages/react-scripts/fixtures/kitchensink/template/src/features/syntax/NullishCoalescing.test.js new file mode 100644 index 00000000000..781896da290 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/template/src/features/syntax/NullishCoalescing.test.js @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; +import NullishCoalescing from './NullishCoalescing'; + +describe('nullish coalescing', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + return new Promise(resolve => { + ReactDOM.render(, div); + }); + }); +}); diff --git a/packages/react-scripts/fixtures/kitchensink/template/src/features/syntax/OptionalChaining.js b/packages/react-scripts/fixtures/kitchensink/template/src/features/syntax/OptionalChaining.js new file mode 100644 index 00000000000..5b0fd1e3e47 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/template/src/features/syntax/OptionalChaining.js @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; + +function load() { + return [ + { id: 1, name: '1' }, + { id: 2, name: '2' }, + { id: 3, name: '3' }, + { id: 4, name: '4' }, + ]; +} + +export default class extends Component { + static propTypes = { + onReady: PropTypes.func.isRequired, + }; + + constructor(props) { + super(props); + this.state = { users: [] }; + } + + async componentDidMount() { + const users = load?.(); + this.setState({ users }); + } + + componentDidUpdate() { + this.props.onReady(); + } + + render() { + return ( +
+ {this.state.users.map(user => ( +
{user?.name}
+ ))} +
+ ); + } +} diff --git a/packages/react-scripts/fixtures/kitchensink/template/src/features/syntax/OptionalChaining.test.js b/packages/react-scripts/fixtures/kitchensink/template/src/features/syntax/OptionalChaining.test.js new file mode 100644 index 00000000000..229037c6de9 --- /dev/null +++ b/packages/react-scripts/fixtures/kitchensink/template/src/features/syntax/OptionalChaining.test.js @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; +import OptionalChaining from './OptionalChaining'; + +describe('optional chaining', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + return new Promise(resolve => { + ReactDOM.render(, div); + }); + }); +});