Repository: mui/material-ui (TypeScript)
Date: 2018-04-07 14:31:24+00:00
Task type: Bug Fix

Issue:
[Select] Menu width does not change after initial render
<!--- Provide a general summary of the issue in the Title above -->

As of #10706 menu min-width is no longer computed for each render. This can cause some display issues when windows are resized.

<!--
    Thank you very much for contributing to Material-UI by creating an issue! ❤️
    To avoid duplicate issues we ask you to check off the following list.
-->

<!-- Checked checkbox should look like this: [x] -->
- [x] I have searched the [issues](https://github.com/mui-org/material-ui/issues) of this repository and believe that this is not a duplicate.

## Expected Behavior
<!---
    If you're describing a bug, tell us what should happen.
    If you're suggesting a change/improvement, tell us how it should work.
-->

After the input is resized the dropdown menu should still match the width of the display node (at least on subsequent renders).

## Current Behavior
<!---
    If describing a bug, tell us what happens instead of the expected behavior.
    If suggesting a change/improvement, explain the difference from current behavior.
-->

![select-resize-bug](https://user-images.githubusercontent.com/1105355/38437820-b560da7c-39a6-11e8-9799-7a02c74cb8c1.gif)

## Steps to Reproduce (for bugs)
<!---
    Provide a link to a live example (you can use codesandbox.io) and an unambiguous set of steps to reproduce this bug.
    Include code to reproduce, if relevant (which it most likely is).

    This codesandbox.io template _may_ be a good starting point:
    https://codesandbox.io/s/github/mui-org/material-ui/tree/v1-beta/examples/create-react-app


    If YOU DO NOT take time to provide a codesandbox.io reproduction, should the COMMUNITY take time to help you?

-->

1. Render a Select component with a variable width (e.g. within a fullWidth FormControl)
2. Resize the window until the input width changes
3. Toggle the dropdown
4. The menu width will be that of the input before step 2

[sandbox](https://codesandbox.io/s/xzjkqx6vq4)

## Context
<!---
    How has this issue affected you? What are you trying to accomplish?
    Providing context helps us come up with a solution that is most useful in the real world.
-->

This can be a problem for responsive designs, especially on mobile browsers where switching from landscape to portrait can cause menu text to be cut off.

Reverting #10706 would fix this issue, but I would imagine #10643 would then return.

## Your Environment
<!--- Include as many relevant details about the environment with which you experienced the bug. -->

| Tech         | Version              |
|--------------|----------------------|
| Material-UI  | 1.0.0-beta.40        |
| React        | 16.3.1               |
| browser      | Chrome, Firefox, iOS |



Issue discussion:
A relevant pull-request: #10706.
@michaelgruber Oh, I see you have done your homework! You have already found the pull-request. Well, what do you think of using the React hooks to update the value storing the width?
@oliviertassinari Yes. I believe you could update `displayWidth` in a `componentWillUpdate` but I'm not sure that's the best solution since it's being deprecated...

I'd also like to point out that [downgrading to React 15](https://codesandbox.io/s/7k85634mj1) fixes #10643. Is it possible that the [original issue](https://github.com/oliviertassinari/react-swipeable-views/issues/417) is with react-swipeable-views after all?

Solution patch:
diff --git a/.size-limit b/.size-limit
--- a/.size-limit
+++ b/.size-limit
@@ -7,13 +7,13 @@
   {
     "name": "The size of the whole library.",
     "path": "build/index.js",
-    "limit": "100.1 KB"
+    "limit": "100.2 KB"
   },
   {
     "name": "The main bundle of the documentation",
     "webpack": false,
     "path": ".next/main.js",
-    "limit": "185 KB"
+    "limit": "184 KB"
   },
   {
     "name": "The home page of the documentation",
diff --git a/src/Select/SelectInput.js b/src/Select/SelectInput.js
--- a/src/Select/SelectInput.js
+++ b/src/Select/SelectInput.js
@@ -29,12 +29,25 @@ class SelectInput extends React.Component {
     }
   }
 
+  shouldComponentUpdate() {
+    this.updateDisplayWidth();
+
+    return true;
+  }
+
   ignoreNextBlur = false;
   displayNode = null;
   displayWidth = null;
   isOpenControlled = this.props.open !== undefined;
   isControlled = this.props.value != null;
 
+  updateDisplayWidth = () => {
+    // Perfom the layout computation outside of the render method.
+    if (this.displayNode) {
+      this.displayWidth = this.displayNode.clientWidth;
+    }
+  };
+
   update = this.isOpenControlled
     ? ({ event, open }) => {
         if (open) {
@@ -129,11 +142,7 @@ class SelectInput extends React.Component {
 
   handleDisplayRef = node => {
     this.displayNode = node;
-
-    if (node) {
-      // Perfom the layout computation outside of the render method.
-      this.displayWidth = node.clientWidth;
-    }
+    this.updateDisplayWidth();
   };
 
   handleSelectRef = node => {


Test patch:
diff --git a/src/Select/SelectInput.test.js b/src/Select/SelectInput.test.js
--- a/src/Select/SelectInput.test.js
+++ b/src/Select/SelectInput.test.js
@@ -279,8 +279,7 @@ describe('<SelectInput />', () => {
   describe('prop: autoWidth', () => {
     it('should take the anchor width into account', () => {
       const wrapper = shallow(<SelectInput {...defaultProps} />);
-      wrapper.instance().displayNode = {};
-      wrapper.instance().displayWidth = 14;
+      wrapper.instance().displayNode = { clientWidth: 14 };
       wrapper.setProps({});
       assert.strictEqual(wrapper.find(Menu).props().PaperProps.style.minWidth, 14);
     });