React v16.3.0: Novos métodos de lifecycle e context API
Marcelo Dapper • 7 de junho de 2018 • ☕️ 6 min de leitura
No post anterior vimos sobre as futuras mudanças em alguns métodos de lifecycle. Na versão 16.3.0 estão sendo adicionados alguns métodos de lifecycle para ajudar com a migração. Também estão sendo introduzidas novas APIs para alguns recursos muito solicitados: uma API oficial para context, uma API para encaminhar refs, e uma API ref mais amigável.
Nota:
Este post é uma tradução do blog oficial do React, você pode ver o artigo original aqui
Nova Context API
Por muitos anos, React ofereceu uma API experimental para context. Embora fosse uma ferramenta poderosa, seu uso era desencorajado por causa de problemas inerentes na API, e porque o objetivo sempre foi que ela fosse substituída por uma API melhor.
A versão 16.3 introduz uma nova API de context que é mais eficiente e suporta tanto verificação de tipos estática, como atualizações profundas.
Nota:
A antiga API de context vai continuar funcionando durante as versões 16.x, assim você terá tempo para migrar.
A seguir um exemplo ilustrando como você pode injetar um “theme” usando a nova API de context:
const ThemeContext = React.createContext('light');
class ThemeProvider extends React.Component {
state = {theme: 'light'};
render() {
return (
<ThemeContext.Provider value={this.state.theme}> {this.props.children} </ThemeContext.Provider> );
}
}
class ThemedButton extends React.Component {
render() {
return (
<ThemeContext.Consumer> {theme => <Button theme={theme} />} </ThemeContext.Consumer> );
}
}
Aprenda mais sobre a nova API de context aqui.
createRef API
Anteriormente, React fornecia duas maneiras de administrar refs: a API legada string ref e a API de callback. Embora a API string ref fosse a mais conveniente das duas, ela tinha várias desvantagens, por isso era recomendado usar a opção com callback.
A versão 16.3 adiciona uma nova opção para administrar refs, que oferece a conveniência de uma string ref, mas sem nenhuma das desvantagens:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef(); }
render() {
return <input type="text" ref={this.inputRef} />; }
componentDidMount() {
this.inputRef.current.focus(); }
}
Nota:
As refs de callback continuam a serem suportados, em adição a nova API
createRef
.Você não precisa substituir refs de callback em seus componentes. Elas são um pouco mais flexíveis, por isso vão permanecer como um recurso avançado.
Aprenda mais sobre a nova API de createRef aqui.
forwardRef API
Geralmente, componentes React são declarativos, mas as vezes acesso imperativo as instâncias do componente e seus nodes DOM são necessárias. Isso é comum para casos de uso como administrar foco, seleção ou animações. React fornece refs como uma forma de resolver este problema. No entanto, encapsulamento de componentes gera alguns desafios com refs.
Por exemplo, se você substitui um <button>
por um componente customizado <FancyButton>
, o atributo ref
nele irá começar a apontar para o componente que o envolve em vez do node DOM (e seria null
para componentes funcionais). Embora isso seja desejável para componentes do “nível de aplicação” como FeedStory
ou Comment
que precisam ser encapsulados, pode ser irritante para componentes como FancyButton
ou MyTextInput
que são tipicamente usados como seus equivalentes DOM, e que precisam expor seus nodes DOM.
Encaminhamento de ref é uma nova funcionalidade opcional que permite alguns componentes pegar um ref
que recebem, e passá-los ainda mais para baixo (em outras palavras, “adiante”) para um filho. No exemplo abaixo, FancyButton
passa sua ref adiante para um button
do DOM que este renderiza:
const FancyButton = React.forwardRef((props, ref) => ( <button ref={ref} className="FancyButton"> {props.children}
</button>
));
// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;
Dessa forma, componentes usando FancyButton
podem pegar o ref do node button
do DOM e acessar, se for necessário, como que diretamente o button
do DOM.
Passar adiante ref não é limitado a componentes que renderizam nodes DOM. Se você escrever componentes higher order, é recomendado passar adiante a ref para as instâncias do componente de classe empacotados.
Aprenda mais sobre a API forwardRef aqui.
Mudanças nos Lifecycle de Componentes
A API de class do React está disponível por bastante tempo já e com poucas alterações. Entretanto, conforme vai sendo adicionado suporte para recursos mais avançados (como error boundaries e o futuro modo async rendering este modelo foi estendido de maneiras que não eram originalmente pretendidas.
Por exemplo, com a API atual, é muito fácil bloquear o render inicial com lógica não essencial. Isso em parte acontece por existirem diversas maneiras de resolver uma tarefa, e pode não ser claro qual é a melhor. O comportamento de interromper, ao lidar com erros, com frequência não é levado em conta e pode resultar em memory leaks (algo que vai também impactar o futuro modo async rendering). A API de class atual também complica outros esforços, como criar um protótipo de um compilador React.
Muitos desses problemas são gerados por uma parte dos métodos de lifecycle (componentWillMount
, componentWillReceiveProps
, e componentWillUpdate
). Estes também acabam sendo os lifecycles que mais causam confusão entre comunidade React. Por estas razões, estes métodos serão depreciados em favor de alternativas melhores.
Esta mudança vai causar impacto em muitos componentes existentes. Por causa disso, a migração será o mais gradual possível, e vão ser providas alternativas. (No Facebook, são mantidos mais de 50.000 componentes React. Eles também dependem de um release gradual)
Nota:
Avisos de depreciação serão habilitados em uma futura versão 16.x, mas os lifecycles legados vão continuar funcionando até a versão 17.
Mesmo na versão 17, ainda será possível usar eles, mas terão um prefix “UNSAFE_” para indicar que eles podem causar problemas. Também foi preparado um script que automatiza renomear eles em código existente.
Além de depreciar lifecycles que não são seguros, estão sendo adicionados dois novos lifecycles:
getDerivedStateFromProps
está sendo adicionado como uma alternativa mais segura ao método legadocomponentWillReceiveProps
.getSnapshotBeforeUpdate
está sendo adicionado para suportar ler propriedades de forma segura do DOM antes que sejam feitos updates.
Aprenda mais sobre estas mudanças de lifecycle aqui.
StrictMode Component
StrictMode
é uma ferramenta para destacar possíveis problemas em uma aplicação. Assim como Fragment
, StrictMode
não renderiza nenhuma UI visível. Ele adiciona verificações adicionais e avisos para os seus descendentes.
Nota:
As verificações
StrictMode
rodam apenas em modo de desenvolvimento; não impactam o build de produção.
Embora não seja possível que o strict mode pegue todos os problemas (por exemplo, algumas mutações de tipos), ele pode ajudar em muitos. Se você ver avisos em strict mode, estes provavelmente vão causar bugs para o async rendering.
Na versão 16.3, StrictMode
ajuda com:
- Identificar componentes com métodos lifecycle que não são seguros
- Avisar sobre usos da API string ref legada
- Detectar efeitos colaterais inesperados
Funcionalidades adicionais serão adicionadas em futuras versões do React.