Open jderusse opened 2 years ago
Thanks for the bug report - it's an interesting one! Would you like to dive deeper and investigate the issue?
@smitgol how does it relate to the problem? There are no warnings about refs.
Tried to dig into the issue, but internal's react is too complicated for me :(
Seems like using a timeout is a workaround. Updated sandbox, https://codesandbox.io/s/nostalgic-fermat-4eyjxr?file=/src/App.jsx
I ran into this same issue today. Maybe it's related to https://reactjs.org/docs/strict-mode.html#ensuring-reusable-state
React 18 introduces a new development-only check to Strict Mode. This new check will automatically unmount and remount every component, whenever a component mounts for the first time, restoring the previous state on the second mount.
You can swap the <Textfield />
for a normal <input />
and get the same result.
Here is the same sandbox without StrictMode, but with a double setTimeout
that trigger the modal to open/hide/open quickly. It also breaks the autofocus.
https://codesandbox.io/s/wandering-dust-vptu4u?file=/src/index.js
Can confirm that disabling <StrictMode>
resolves the issue. Likely the mount/remount behaviour causing the issue.
The workaround does not work for me. Is it even possible to programmatically focus the TextField
component?
Any updates on this? I can confirm this is still an issue as of @mui/material 5.11.10
.
Me as well, observing the same behavior.
This came up in a StackOverflow issue: https://stackoverflow.com/questions/75644447/autofocus-not-working-on-open-form-dialog-with-button-component-in-material-ui-v.
I believe it is a "bug" in the restore-focus functionality in FocusTrap
-- if I add the disableRestoreFocus
prop to the Dialog
the auto focus works. When the incorrect behavior occurs, focus does go briefly to the text field but then returns immediately to the button.
I believe the restore focus functionality is executing on open of the dialog. In strict mode with the dev react build, the FocusTrap component is being mounted twice, and the unmount after the first mount causes focus to be restored to the button.
I'm not seeing any easy way to fix this. It is correct for focus to be restored to the button during unmount, but I don't think the dialog and text field DOM elements are actually being unmounted -- it's just a re-execution of their mount lifecycle. So the second mount brings focus back to the dialog, but the text field auto-focus functionality doesn't re-execute since it was never removed/re-added to the DOM. This doesn't seem to be as much a bug in FocusTrap
as it is an unfortunate side effect of the React 18 dev build strict mode behavior.
Just encountered this as well. Looks like there's two options judging from the thread history for those on React 18+. Thanks for everyone who contributed.
1) Ensure that the TextField autofocuses in the intended way in the production build and leave everything else as is.
2) Set disableRestoreFocus
prop to true
on the Dialog component but lose that functionality, which is described as follows:
If true, the focus trap will not restore focus to previously focused element once focus trap is hidden or unmounted.
So, if the user's focus is inside a TextField, and they click a button or perform some action that causes a Dialog to open, the focus will not automatically return to that TextField when the Dialog is closed. Instead, they'll need to manually click into it again.
Adding an update for Dec 2023
Can still reproduce this TextField inside Dialog autoFocus behaviour on
"@mui/material": "^5.15.0"
"react": "^18.2.0"
@SikandAlex's solution works for me disableRestoreFocus
on the Dialog with autoFocus
on the child TextField
Strict Mode is enabled
ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<App />
</React.StrictMode>
);
I'm also using Vite tooling, but no special configurations here.
ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠΉ Π·Π° Π΄Π΅ΠΊΠ°Π±ΡΡ 2023 Π³.
ΠΡΠ΅ Π΅ΡΠ΅ ΠΌΠΎΠΆΠ½ΠΎ Π²ΠΎΡΠΏΡΠΎΠΈΠ·Π²Π΅ΡΡΠΈ ΡΡΠΎ TextField Π²Π½ΡΡΡΠΈ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΡ Π°Π²ΡΠΎΡΠΎΠΊΡΡΠΈΡΠΎΠ²ΠΊΠΈ Π΄ΠΈΠ°Π»ΠΎΠ³Π° Π½Π°
"@mui/material": "^5.15.0"
"react": "^18.2.0"
@SikandAlexΡΠ΅ΡΠ΅Π½ΠΈΠ΅ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ Π΄Π»Ρ ΠΌΠ΅Π½Ρ
disableRestoreFocus
Π² Π±Π»ΠΈΠΆΠ°ΠΉΡΠ΅ΠΌ ΠΎΠΊΠ½Π΅ ΡautoFocus
Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΡΠΌ ΡΠ΅ΠΊΡΡΠΎΠ²ΡΠΌ ΠΏΠΎΠ»Π΅ΠΌΠ‘ΡΡΠΎΠ³ΠΈΠΉ ΡΠ΅ΠΆΠΈΠΌ Π²ΠΊΠ»ΡΡΠ΅Π½
ReactDOM.createRoot(document.getElementById("root")!).render( <React.StrictMode> <App /> </React.StrictMode> );
Π― ΡΠ°ΠΊΠΆΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΡ Vite, Π½ΠΎ Π½ΠΈΠΊΠ°ΠΊΠΈΡ ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΡΡ Π½Π°ΡΡΡΠΎΠ΅ΠΊ Π·Π΄Π΅ΡΡ Π½Π΅Ρ.
https://github.com/mui/material-ui/assets/95183545/0a1ca141-efda-4241-b918-c8c135fca649
When using disableRestoreFocus
the focus on the button is broken when closing the modal window via the keyboard
I also encountered this problem. Thanks for all the answers above! Here's a quick recap of what worked for me.
It should work if your TextField is in a Dialog, and you're using React 18+ with Strict Mode enabled and MUI 15+
disableRestoreFocus
prop.autoFocus
prop.<Dialog disableRestoreFocus {...otherProps}>
...
<TextField autoFocus {...otherProps}/>
</Dialog>
In certain cases this has the downside mentioned in @SikandAlex's comment above but thankfully that did not apply to me π
So, if the user's focus is inside a TextField, and they click a button or perform some action that causes a Dialog to open, the focus will not automatically return to that TextField when the Dialog is closed. Instead, they'll need to manually click into it again.
Using disableRestoreFocus
didn't work for me. I had a single TextField
component inside DialogContent
.
I had to use a timeout workaround.
Same issue happened to me and since I had a multiple input elements I found another way to keep autoFocus in focused element and the solution is;
const [state, setState] = useState({
openDialog: false,
address: {},
formError: {},
autoFocus: ''
});
I defined an autoFocus
field in my state and set the field name in each input value like;
<TextField
required
id="firstName"
name="firstName"
label="First name"
error={!!errors["firstName"]}
helperText={errors["firstName"]}
value={address.firstName}
onChange={(e) =>{
setState((prev) => ({
...prev,
address: { ...prev.address, firstName: e.target.value },
}))
}}
fullWidth
variant="standard"
onClickCapture={() => setState(prev => ({ ...prev, autoFocus: 'firstName' }))}
autoFocus={autoFocus === 'firstName'}
/>
by doing this I can capture the focused element and I set autoFocus for that particular element and issue has gone!
Duplicates
Latest version
Current behavior π―
When switching to
ReactDOM.createRoot
, opening a Dialog containing a TextField withautofocus
, the field is not focused.Expected behavior π€
No response
Steps to reproduce πΉ
reproducer: reproducer : https://codesandbox.io/s/dreamy-kowalevski-8eu5fb?file=/src/index.js
Context π¦
The Dialog + field
When initializing the project with the previous version of react it worked. But react triggered the deprecation about switching to
ReactDOM.createRoot
When switching to
ReactDOM.createRoot
it does not workedBut, if I remove the
StrictMode
, it workYour environment π
`npx @mui/envinfo`
``` System: OS: Linux 5.10 Debian GNU/Linux 11 (bullseye) 11 (bullseye) Binaries: Node: 17.9.0 - /usr/bin/node Yarn: 3.1.1 - /usr/local/bin/yarn npm: 8.10.0 - /usr/bin/npm Browsers: Chrome: 102.0.5005.61 Firefox: 91.10.0esr npmPackages: @emotion/react: ^11.9.0 => 11.9.0 @emotion/styled: ^11.8.1 => 11.8.1 @mui/base: 5.0.0-alpha.83 @mui/icons-material: ^5.8.2 => 5.8.2 @mui/material: ^5.8.2 => 5.8.2 @mui/private-theming: 5.8.0 @mui/styled-engine: 5.8.0 @mui/system: 5.8.2 @mui/types: 7.1.3 @mui/utils: 5.8.0 @types/react: ^18.0.10 => 18.0.10 react: ^18.1.0 => 18.1.0 react-dom: ^18.1.0 => 18.1.0 typescript: ^4.7.2 => 4.7.2 ```