Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

250
Visualizações
MUI TextField inside Custom Tooltip loses focus when state changes

I'm using MUI, and I've got a custom Tooltip around one TextField in a form. As soon as I type anything in that particular TextField, it loses focus. It updates the state of that value of my formData object to the one character I was able to type, so that value is only ever one character long. The other TextFields in my form work as expected. If I replace the custom Tooltip with a standard one, that particular TextField works fine, too. I've replicated the issue on codesandbox. Here's the code I used there:

import { useState } from "react";
import { TextField, Box } from "@mui/material";
import { styled } from "@mui/material/styles";
import Tooltip, { tooltipClasses } from "@mui/material/Tooltip";

export default function App() {
  const [formData, setFormData] = useState({
    title: "",
    name: ""
  });

  const handleFormChange = (e) => {
    const { name, value } = e.target;
    setFormData((formData) => {
      return {
        ...formData,
        [name]: value
      };
    });
  };

  const CustomWidthTooltip = styled(({ className, ...props }) => (
    <Tooltip {...props} classes={{ popper: className }} />
  ))({
    [`& .${tooltipClasses.tooltip}`]: {
      maxWidth: 400
    }
  });

  return (
    <Box component="form" display="flex">
      // THIS ONE WORKS JUST FINE 
      <TextField
        onChange={handleFormChange}
        autoComplete="title"
        name="title"
        id="title"
        label="Title"
        required
      />
      // THIS ONE IS BROKEN
      <CustomWidthTooltip title="Foo">
        <TextField
          onChange={handleFormChange}
          autoComplete="name"
          name="name"
          id="name"
          label="Name"
          required
        />
      </CustomWidthTooltip>
    </Box>
  );
}

Thanks for your help, folks! I appreciate you all.

about 4 years ago · Juan Pablo Isaza
2 Respostas
Responde à pergunta

0

You're initializing CustomWidthTooltip inside the App component, which is causing the tooltip to reintialize on local state change. Whenever the name is updated inside formData local state, the TextField inside the CustomWidthTooltip component is being recreated in the UI, causing the focus loss as a result.

You should move the CustomWidthTooltip out of the component App.

Updated Code

import "./styles.css";
import { useState } from "react";
import { TextField, Box } from "@mui/material";
import { styled } from "@mui/material/styles";
import Tooltip, { tooltipClasses } from "@mui/material/Tooltip";

const CustomWidthTooltip = styled(({ className, ...props }) => (
  <Tooltip {...props} classes={{ popper: className }} />
))({
  [`& .${tooltipClasses.tooltip}`]: {
    maxWidth: 400
  }
});

export default function App() {
  const [formData, setFormData] = useState({
    title: "",
    name: ""
  });
  console.log("formData", formData);

  const handleFormChange = (e) => {
    const { name, value } = e.target;
    console.log({ name, value });
    setFormData((formData) => {
      return {
        ...formData,
        [name]: value
      };
    });
  };

  return (
    <div>
      <h3>With a custom tooltip, it's broken:</h3>
      <Box component="form" display="flex">
        <TextField
          onChange={handleFormChange}
          autoComplete="title"
          name="title"
          id="title"
          label="Title"
          required
        />
        <CustomWidthTooltip title="Custom Custom Custom Custom Custom Custom">
          <TextField
            onChange={handleFormChange}
            autoComplete="name"
            name="name"
            id="name"
            label="Name"
            required
          />
        </CustomWidthTooltip>
      </Box>
      <h3>With a standard tooltip, it works:</h3>
      <Box component="form" display="flex">
        <TextField
          onChange={handleFormChange}
          autoComplete="title"
          name="title"
          id="title"
          label="Title"
          required
        />
        <Tooltip title="Standard">
          <TextField
            onChange={handleFormChange}
            autoComplete="name"
            name="name"
            id="name"
            label="Name"
            required
          />
        </Tooltip>
      </Box>
    </div>
  );
}

Edit gallant-dijkstra-9fynn

about 4 years ago · Juan Pablo Isaza Relatório

0

As Junaid mentioned, you are re-rendering the tooltip which is why it flashes.

I would personally use their solution and even move custom styled components into another file seeing as you will probably want to reuse them elsewhere.

Regardless, another alternative is the useMemo hook. This is a good opportunity for you to learn about how it can help.

You can leave your CustomWidthTooltip function where it is but just wrap it in useMemo:

import { useState, useMemo } from "react";

...

  const CustomWidthTooltip = useMemo(
    () =>
      styled(({ className, ...props }) => (
        <Tooltip {...props} classes={{ popper: className }} />
      ))({
        [`& .${tooltipClasses.tooltip}`]: {
          maxWidth: 400
        }
      }),
    [listOfDependencies]
  );

...

So this will calculate the styled component and store it to your variable, but it will not recreate it on subsequent renders. The array as the second parameter ([listOfDependencies]), is where you can add variables that it should watch. If there is any change to these variables, it will recompute CustomWidthTooltip.

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda