Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React v16.8.5 #15192

Closed
wants to merge 12 commits into from
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,24 @@
</summary>
</details>

## 16.8.5 (March 22, 2019)

### React DOM

* Don't set the first option as selected in select tag with `size` attribute. ([@kulek1](https://github.com/kulek1) in [#14242](https://github.com/facebook/react/pull/14242))
* Improve the `useEffect(async () => ...)` warning message. ([@gaearon](https://github.com/gaearon) in [#15118](https://github.com/facebook/react/pull/15118))
* Improve the error message sometimes caused by duplicate React. ([@jaredpalmer](https://github.com/jaredpalmer) in [#15139](https://github.com/facebook/react/pull/15139))

### React DOM Server

* Improve the `useLayoutEffect` warning message when server rendering. ([@gaearon](https://github.com/gaearon) in [#15158](https://github.com/facebook/react/pull/15158))

### React Shallow Renderer

* Fix `setState` in shallow renderer to work with Hooks. ([@gaearon](https://github.com/gaearon) in [#15120](https://github.com/facebook/react/pull/15120))
* Fix shallow renderer to support `React.memo`. ([@aweary](https://github.com/aweary) in [#14816](https://github.com/facebook/react/pull/14816))
* Fix shallow renderer to support Hooks inside `forwardRef`. ([@eps1lon](https://github.com/eps1lon) in [#15100](https://github.com/facebook/react/pull/15100))

## 16.8.4 (March 5, 2019)

### React DOM and other renderers
Expand Down
28 changes: 28 additions & 0 deletions fixtures/dom/src/components/fixtures/selects/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,34 @@ class SelectFixture extends React.Component {
</select>
</div>
</TestCase>

<TestCase
title="A select with the size attribute should not set first option as selected"
relatedIssues="14239"
introducedIn="16.0.0">
<TestCase.ExpectedResult>
No options should be selected.
</TestCase.ExpectedResult>

<div className="test-fixture">
<select size="3">
<option>0</option>
<option>1</option>
<option>2</option>
</select>
</div>

<p className="footnote">
<b>Notes:</b> This happens if <code>size</code> is assigned after
options are selected. The select element picks the first item by
default, then it is expanded to show more options when{' '}
<code>size</code> is assigned, preserving the default selection.
</p>
<p className="footnote">
This was introduced in React 16.0.0 when options were added before
select attribute assignment.
</p>
</TestCase>
</FixtureSet>
);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/create-subscription/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "create-subscription",
"description": "utility for subscribing to external data sources inside React components",
"version": "16.8.4",
"version": "16.8.5",
"repository": {
"type": "git",
"url": "https://github.com/facebook/react.git",
Expand Down
2 changes: 1 addition & 1 deletion packages/jest-react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jest-react",
"version": "0.6.4",
"version": "0.6.5",
"description": "Jest matchers and utilities for testing React components.",
"main": "index.js",
"repository": {
Expand Down
4 changes: 2 additions & 2 deletions packages/react-art/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "react-art",
"description": "React ART is a JavaScript library for drawing vector graphics using React. It provides declarative and reactive bindings to the ART library. Using the same declarative API you can render the output to either Canvas, SVG or VML (IE8).",
"version": "16.8.4",
"version": "16.8.5",
"main": "index.js",
"repository": {
"type": "git",
Expand All @@ -27,7 +27,7 @@
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
"prop-types": "^15.6.2",
"scheduler": "^0.13.4"
"scheduler": "^0.13.5"
},
"peerDependencies": {
"react": "^16.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,12 @@ describe('ReactHooksInspection', () => {
expect(() => {
ReactDebugTools.inspectHooks(Foo, {}, FakeDispatcherRef);
}).toThrow(
'Hooks can only be called inside the body of a function component.',
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
' one of the following reasons:\n' +
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
'2. You might be breaking the Rules of Hooks\n' +
'3. You might have more than one copy of React in the same app\n' +
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
);

expect(getterCalls).toBe(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,12 @@ describe('ReactHooksInspectionIntegration', () => {
expect(() => {
ReactDebugTools.inspectHooksOfFiber(childFiber, FakeDispatcherRef);
}).toThrow(
'Hooks can only be called inside the body of a function component.',
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
' one of the following reasons:\n' +
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
'2. You might be breaking the Rules of Hooks\n' +
'3. You might have more than one copy of React in the same app\n' +
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
);

expect(getterCalls).toBe(1);
Expand Down
4 changes: 2 additions & 2 deletions packages/react-dom/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-dom",
"version": "16.8.4",
"version": "16.8.5",
"description": "React package for working with the DOM.",
"main": "index.js",
"repository": {
Expand All @@ -20,7 +20,7 @@
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
"prop-types": "^15.6.2",
"scheduler": "^0.13.4"
"scheduler": "^0.13.5"
},
"peerDependencies": {
"react": "^16.0.0"
Expand Down
26 changes: 26 additions & 0 deletions packages/react-dom/src/__tests__/ReactDOMSelect-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,32 @@ describe('ReactDOMSelect', () => {
expect(node.options[2].selected).toBe(true); // gorilla
});

it('does not select an item when size is initially set to greater than 1', () => {
const stub = (
<select size="2">
<option value="monkey">A monkey!</option>
<option value="giraffe">A giraffe!</option>
<option value="gorilla">A gorilla!</option>
</select>
);
const container = document.createElement('div');
const select = ReactDOM.render(stub, container);

expect(select.options[0].selected).toBe(false);
expect(select.options[1].selected).toBe(false);
expect(select.options[2].selected).toBe(false);

// Note: There is an inconsistency between JSDOM and Chrome where
// Chrome reports an empty string when no value is selected for a
// single-select with a size greater than 0. JSDOM reports the first
// value
//
// This assertion exists only for clarity of JSDOM behavior:
expect(select.value).toBe('monkey'); // "" in Chrome
// Despite this, the selection index is correct:
expect(select.selectedIndex).toBe(-1);
});

it('should remember value when switching to uncontrolled', () => {
let stub = (
<select value={'giraffe'} onChange={noop}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,12 @@ describe('ReactDOMServerHooks', () => {

return render(<Counter />);
},
'Hooks can only be called inside the body of a function component.',
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
' one of the following reasons:\n' +
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
'2. You might be breaking the Rules of Hooks\n' +
'3. You might have more than one copy of React in the same app\n' +
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
);

itRenders('multiple times when an updater is called', async render => {
Expand Down Expand Up @@ -626,7 +631,12 @@ describe('ReactDOMServerHooks', () => {

return render(<Counter />);
},
'Hooks can only be called inside the body of a function component.',
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
' one of the following reasons:\n' +
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
'2. You might be breaking the Rules of Hooks\n' +
'3. You might have more than one copy of React in the same app\n' +
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
);
});

Expand Down
23 changes: 17 additions & 6 deletions packages/react-dom/src/client/ReactDOMComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -419,14 +419,25 @@ export function createElement(
// See discussion in https://github.com/facebook/react/pull/6896
// and discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1276240
domElement = ownerDocument.createElement(type);
// Normally attributes are assigned in `setInitialDOMProperties`, however the `multiple`
// attribute on `select`s needs to be added before `option`s are inserted. This prevents
// a bug where the `select` does not scroll to the correct option because singular
// `select` elements automatically pick the first item.
// Normally attributes are assigned in `setInitialDOMProperties`, however the `multiple` and `size`
// attributes on `select`s needs to be added before `option`s are inserted.
// This prevents:
// - a bug where the `select` does not scroll to the correct option because singular
// `select` elements automatically pick the first item #13222
// - a bug where the `select` set the first item as selected despite the `size` attribute #14239
// See https://github.com/facebook/react/issues/13222
if (type === 'select' && props.multiple) {
// and https://github.com/facebook/react/issues/14239
if (type === 'select') {
const node = ((domElement: any): HTMLSelectElement);
node.multiple = true;
if (props.multiple) {
node.multiple = true;
} else if (props.size) {
// Setting a size greater than 1 causes a select to behave like `multiple=true`, where
// it is possible that no option is selected.
//
// This is only necessary when a select in "single selection mode".
node.size = props.size;
}
}
}
} else {
Expand Down
11 changes: 8 additions & 3 deletions packages/react-dom/src/server/ReactPartialRendererHooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,12 @@ let currentHookNameInDev: ?string;
function resolveCurrentlyRenderingComponent(): Object {
invariant(
currentlyRenderingComponent !== null,
'Hooks can only be called inside the body of a function component. ' +
'(https://fb.me/react-invalid-hook-call)',
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
' one of the following reasons:\n' +
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
'2. You might be breaking the Rules of Hooks\n' +
'3. You might have more than one copy of React in the same app\n' +
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
);
if (__DEV__) {
warning(
Expand Down Expand Up @@ -389,7 +393,8 @@ export function useLayoutEffect(
"be encoded into the server renderer's output format. This will lead " +
'to a mismatch between the initial, non-hydrated UI and the intended ' +
'UI. To avoid this, useLayoutEffect should only be used in ' +
'components that render exclusively on the client.',
'components that render exclusively on the client. ' +
'See https://fb.me/react-uselayouteffect-ssr for common fixes.',
);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/react-is/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-is",
"version": "16.8.4",
"version": "16.8.5",
"description": "Brand checking of React Elements.",
"main": "index.js",
"repository": {
Expand Down
4 changes: 2 additions & 2 deletions packages/react-reconciler/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "react-reconciler",
"description": "React package for creating custom renderers.",
"version": "0.20.2",
"version": "0.20.3",
"keywords": [
"react"
],
Expand Down Expand Up @@ -33,7 +33,7 @@
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
"prop-types": "^15.6.2",
"scheduler": "^0.13.4"
"scheduler": "^0.13.5"
},
"browserify": {
"transform": [
Expand Down
21 changes: 11 additions & 10 deletions packages/react-reconciler/src/ReactFiberCommitWork.js
Original file line number Diff line number Diff line change
Expand Up @@ -346,22 +346,23 @@ function commitHookEffectList(
} else if (typeof destroy.then === 'function') {
addendum =
'\n\nIt looks like you wrote useEffect(async () => ...) or returned a Promise. ' +
'Instead, you may write an async function separately ' +
'and then call it from inside the effect:\n\n' +
'async function fetchComment(commentId) {\n' +
' // You can await here\n' +
'}\n\n' +
'Instead, write the async function inside your effect ' +
'and call it immediately:\n\n' +
'useEffect(() => {\n' +
' fetchComment(commentId);\n' +
'}, [commentId]);\n\n' +
'In the future, React will provide a more idiomatic solution for data fetching ' +
"that doesn't involve writing effects manually.";
' async function fetchData() {\n' +
' // You can await here\n' +
' const response = await MyAPI.getData(someId);\n' +
' // ...\n' +
' }\n' +
' fetchData();\n' +
`}, [someId]); // Or [] if effect doesn't need props or state\n\n` +
'Learn more about data fetching with Hooks: https://fb.me/react-hooks-data-fetching';
} else {
addendum = ' You returned: ' + destroy;
}
warningWithoutStack(
false,
'An Effect function must not return anything besides a function, ' +
'An effect function must not return anything besides a function, ' +
'which is used for clean-up.%s%s',
addendum,
getStackByFiberInDevAndProd(finishedWork),
Expand Down
8 changes: 6 additions & 2 deletions packages/react-reconciler/src/ReactFiberHooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,12 @@ function warnOnHookMismatchInDev(currentHookName: HookType) {
function throwInvalidHookError() {
invariant(
false,
'Hooks can only be called inside the body of a function component. ' +
'(https://fb.me/react-invalid-hook-call)',
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
' one of the following reasons:\n' +
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
'2. You might be breaking the Rules of Hooks\n' +
'3. You might have more than one copy of React in the same app\n' +
'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
);
}

Expand Down
Loading