componentDidMount equivalente em uma função React / componente Hooks?


Respostas:


216

Para a versão estável dos ganchos (React versão 16.8.0+)

Para componentDidMount

useEffect(() => {
  // Your code here
}, []);

Para componentDidUpdate

useEffect(() => {
  // Your code here
}, [yourDependency]);

Para componentWillUnmount

useEffect(() => {
  // componentWillUnmount
  return () => {
     // Your code here
  }
}, [yourDependency]);

Portanto, nesta situação, você precisa passar sua dependência para este array. Vamos supor que você tenha um estado como este

const [count, setCount] = useState(0);

E sempre que a contagem aumenta, você deseja renderizar novamente o componente de função. Então você useEffectdeve se parecer com isto

useEffect(() => {
  // <div>{count}</div>
}, [count]);

Dessa forma, sempre que sua contagem for atualizada, seu componente será renderizado novamente. Espero que isso ajude um pouco.


Explicação completa! Existe uma maneira de simular o componentDidReceiveProps?
— jeyko

1
Não estou ciente disso, mesmo que exista. Você pode verificar este tópico em github.com/facebook/react/issues/3279
— Mertcan Diken

1
Obrigado por isso, pois eu não estava ciente do segundo argumento em useState. Para quem undefinedestiver lendo isso, lembre-se de que deixar o segundo argumento fará com que seu efeito seja acionado em cada renderização (se não estou enganado).
— dimiguel

Você quer dizer dependências de useEffect (passando uma matriz de dependência)? Se sim, se você deixar vazio, isso é um bug no código. Para a desconstrução da matriz, você precisa de [count, setCount] porque count é sua variável de estado neste exemplo e setCount é sua função para atualizar esse estado.
— Mertcan Diken

1
Tenho tentado usar a matriz de dependência vazia para simular o componentDidMount. O problema é que geralmente resulta em um aviso: "React Hook useEffect tem uma dependência ausente: <some prop>. Inclua-a ou remova a matriz de dependência react-hooks / exaustive-deps". Aplicar qualquer uma das "correções" sugeridas faz com que ele não se comporte mais como componentDidMount. Estou fazendo algo errado?
— Jonas Rosenqvist

3

Embora a resposta aceita funcione, não é recomendada. Quando você tem mais de um estado e o usa com useEffect, ele avisa sobre como adicioná-lo ao array de dependências ou não usá-lo.

Às vezes, causa problemas que podem gerar resultados imprevisíveis. Portanto, sugiro que você se esforce um pouco para reescrever sua função como classe. Existem muito poucas mudanças, e você pode ter alguns componentes como classe e alguns como função. Você não é obrigado a usar apenas uma convenção.

Veja isso por exemplo

function App() {
  const [appointments, setAppointments] = useState([]);
  const [aptId, setAptId] = useState(1);

  useEffect(() => {
    fetch('./data.json')
      .then(response => response.json())
      .then(result => {
        const apts = result.map(item => {
          item.aptId = aptId;
          console.log(aptId);
          setAptId(aptId + 1);
          return item;
        })
        setAppointments(apts);
      });
  }, []);

  return(...);
}

e

class App extends Component {
  constructor() {
    super();
    this.state = {
      appointments: [],
      aptId: 1,
    }
  }

  componentDidMount() {
    fetch('./data.json')
      .then(response => response.json())
      .then(result => {
        const apts = result.map(item => {
          item.aptId = this.state.aptId;
          this.setState({aptId: this.state.aptId + 1});
          console.log(this.state.aptId);
          return item;
        });
        this.setState({appointments: apts});
      });
  }

  render(...);
}

Isso é apenas por exemplo . portanto, não vamos falar sobre as melhores práticas ou possíveis problemas com o código. Ambos têm a mesma lógica, mas o último funciona apenas conforme o esperado. Você pode obter a funcionalidade componentDidMount com useEffect em execução neste momento, mas conforme seu aplicativo cresce, há chances de que você possa enfrentar alguns problemas. Portanto, em vez de reescrever nessa fase, é melhor fazer isso no estágio inicial.

Além disso, OOP não é tão ruim assim, se a Programação Orientada a Procedimentos fosse suficiente, nunca teríamos tido a Programação Orientada a Objetos. É doloroso às vezes, mas melhor (tecnicamente. Questões pessoais à parte).


1
Eu fiz isso. Eu enfrentei problema usando ganchos. O problema desapareceu depois de convertê-lo em classe.
— Julez

2

Não há componentDidMountcomponentes funcionais, mas os Ganchos React fornecem uma maneira de emular o comportamento usando o useEffectgancho.

Passe uma matriz vazia como o segundo argumento useEffect()para executar apenas o retorno de chamada na montagem.

Por favor, leia a documentação emuseEffect .

function ComponentDidMount() {
  const [count, setCount] = React.useState(0);
  React.useEffect(() => {
    console.log('componentDidMount');
  }, []);

  return (
    <div>
      <p>componentDidMount: {count} times</p>
      <button
        onClick={() => {
          setCount(count + 1);
        }}
      >
        Click Me
      </button>
    </div>
  );
}

ReactDOM.render(
  <div>
    <ComponentDidMount />
  </div>,
  document.querySelector("#app")
);
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>


1

Não há equivalente exato para componentDidMountganchos de reação.


Na minha experiência, os hooks react requerem uma mentalidade diferente ao desenvolvê-los e, de modo geral, você não deve compará-los aos métodos de classe como componentDidMount.

Com isso dito, há maneiras de usar ganchos para produzir um efeito semelhante ao componentDidMount.

Solução 1:

useEffect(() => {
  console.log("I have been mounted")
}, [])

Solução 2:

const num = 5

useEffect(() => {
  console.log("I will only run if my deps change: ", num)
}, [num])

Solução 3 (com função):

useEffect(() => {
  const someFunc = () => {
    console.log("Function being run after/on mount")
  }
  someFunc()
}, [])

Solução 4 (useCallback):

const msg = "some message"

const myFunc = useCallback(() => {
  console.log(msg)
}, [msg])

useEffect(() => {
  myFunc()
}, [myFunc])

Solução 5 (ser criativo):

export default function useDidMountHook(callback) {
  const didMount = useRef(null)

  useEffect(() => {
    if (callback && !didMount.current) {
      didMount.current = true
      callback()
    }
  })
}

É importante notar que a solução 5 só deve ser usada realmente se nenhuma das outras soluções funcionar para seu caso de uso . Se você decidir que precisa da solução 5, recomendo usar este gancho pré-fabricado use-did-mount .

Fonte (com mais detalhes): Usando componentDidMount em react hooks


0

o gancho equivalente exato para componentDidMount () é

useEffect(()=>{},[]);

espero que seja útil :)


-1

Você deseja usar useEffect(), que, dependendo de como você usa a função, pode atuar como componentDidMount ().

Por exemplo. você pode usar uma loadedpropriedade de estado customizada que é inicialmente definida como false e alterná-la para true na renderização e apenas disparar o efeito quando esse valor mudar.

Documentação


1
Esta solução não é ideal. É uma má ideia usar um valor de estado apenas para determinar se o componente foi montado. Além disso, se você fosse usar uma propriedade, um ref seria melhor, pois não acionaria outra renderização.
— Yangshun Tay
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.