why-did-you-render
de Welldone Software parches de mono React
para notificarle sobre re-renderizaciones potencialmente evitables. (También funciona con React Native
).
Por ejemplo, si pasa style={{width: '100%'}}
a un componente puro grande, siempre se volverá a representar en cada creación de elemento:
<BigListPureComponent estilo={{ancho: '100%'}}/>
También puede ayudarle a realizar un seguimiento sencillo de cuándo y por qué se vuelve a renderizar un determinado componente.
Se probó la última versión de la biblioteca (pruebas unitarias y E2E) solo con React@18
. Para React 17 y 16, utilice la versión @^7.
npm install @welldone-software/why-did-you-render --save-dev
o
yarn add --dev @welldone-software/why-did-you-render
Si utiliza la transformación JSX automatic
, configure la biblioteca para que sea la fuente de importación y asegúrese de que preset-react
esté en modo de development
.
['@babel/preset-react', { tiempo de ejecución: 'automático', desarrollo: proceso.env.NODE_ENV === 'desarrollo', importSource: '@welldone-software/por qué-hiciste-render',}]
Desafortunadamente, el metro-react-native-babel-preset
que viene con reaccionar-native listo para usar no le permite cambiar las opciones del complemento babel/plugin-transform-react-jsx
. Simplemente agregue el complemento con las opciones que se enumeran a continuación e inicie el empaquetador nativo de reacción como de costumbre. El entorno predeterminado para Babel es "desarrollo". Si no utiliza expo cuando trabaja con reaccionar-nativo, el siguiente método le ayudará.
module.exports = { ajustes preestablecidos: ['module:metro-react-native-babel-preset'], env: { desarrollo: { complementos: [['@babel/plugin-transform-react-jsx', { tiempo de ejecución: ' clásico' }]], }, },}
Puedes pasar parámetros a @babel/preset-react
a través de babel-preset-expo
// babel.config.jsmodule.exports = función (api) { api.cache(true); return { presets: [ [ "babel-preset-expo", { jsxImportSource: "@welldone-software/porque-renderizaste", }, ], ], };};
Aviso: Create React App (CRA) ^4 utiliza la transformación JSX
automatic
. Vea el siguiente comentario sobre cómo hacer este paso con CRA
Cree un archivo wdyr.js
e impórtelo como la primera importación en su aplicación.
wdyr.js
:
importar React desde 'react';if (process.env.NODE_ENV === 'desarrollo') { constWhyDidYouRender = require('@welldone-software/why-did-you-render'); WhyDidYouRender (React, { trackAllPureComponents: true, });}
Aviso: la biblioteca NUNCA debe usarse en producción porque ralentiza React
En Typecript, llame al archivo wdyr.ts y agregue la siguiente línea en la parte superior del archivo para importar los tipos del paquete:
/// <tipos de referencia="@welldone-software/por qué-renderizaste" />
Importe wdyr
como primera importación (incluso antes de react-hot-loader
):
index.js
:
importar './wdyr'; // <--- primera importaciónimportar 'react-hot-loader';importar {hot} desde 'react-hot-loader/root';importar React desde 'react';importar ReactDOM desde 'react-dom';// . ..importar {Aplicación} desde './app';// ...const HotApp = hot(App);// ...ReactDOM.render(<HotApp/>, document.getElementById('raíz'));
Si utiliza trackAllPureComponents
como sugerimos, se realizará un seguimiento de todos los componentes puros (React.PureComponent o React.memo).
De lo contrario, agregueWhyDidYouRender whyDidYouRender = true
a las clases/funciones de componentes que desea rastrear. (fe Component.whyDidYouRender = true
)
Puede encontrar más información sobre lo que se rastrea en Componentes de seguimiento.
¿No ves ningún registro WDYR? Consulte la sección de solución de problemas o busque en los problemas.
Además, es posible realizar un seguimiento de los ganchos personalizados mediante trackExtraHooks
. Por ejemplo, si desea realizar un seguimiento de useSelector
de React Redux:
wdyr.js
:
import React from 'react';// Para reaccionar nativo es posible que quieras usar // el indicador __DEV__ en lugar de process.env.NODE_ENV === 'development'if (process.env.NODE_ENV === 'development') { const por quéDidYouRender = require('@welldone-software/por qué-renderizaste'); const ReactRedux = require('react-redux'); WhyDidYouRender(React, { trackAllPureComponents: true, trackExtraHooks: [ [ReactRedux, 'useSelector'] ] });}
Tenga en cuenta que actualmente existe un problema al reescribir las exportaciones de archivos importados en
webpack
. Una solución rápida puede ayudar: #85 - trackExtraHooks no puede establecer la propiedad.
¿Por qué renderizaste el componente Mr. Big Pure React?
Escenarios de reparación comunes con los que esta biblioteca puede ayudar
React Hooks : comprender y solucionar problemas de ganchos
¿Por qué se lanzó Render v4? - Compatibilidad con TypeScript, seguimiento de enlaces personalizados (como useSelector de React-Redux), seguimiento de todos los componentes puros.
Ejemplo de Next.js
Reaccionar-Redux con ganchos
Mobx actualmente no es compatible
Complemento flipper React-Native creado por @allen-hsu
Puedes probar la biblioteca en el sandbox oficial.
Y otro sandbox oficial con seguimiento de ganchos.
Puede realizar un seguimiento de todos los componentes puros (React.PureComponent o React.memo) utilizando la opción trackAllPureComponents: true
.
También puede realizar un seguimiento manual de cualquier componente que desee estableciendo en whyDidYouRender
de esta manera:
class BigList extends React.Component { staticWhyDidYouRender = true render(){ return (//algún renderizado pesado que deseas asegurarte de que no suceda si no es necesario) }}
O para componentes funcionales:
const BigListPureComponent = accesorios => ( <div> //algún componente pesado que deseas asegurarte de que no suceda si no es necesario </div>)BigListPureComponent.whyDidYouRender = true
También puede pasar un objeto para especificar configuraciones de seguimiento más avanzadas:
EnhancedMenu.whyDidYouRender = { logOnDifferentValues: verdadero, nombre personalizado: 'Menú'}
logOnDifferentValues
:
Normalmente, solo se vuelven a renderizar las notificaciones causadas por valores iguales en accesorios/estado:
renderizar(<Menú a={1}/>)render(<Menú a={1}/>)
Esta opción activará notificaciones incluso si ocurrieron debido a diferentes accesorios/estados (por lo tanto, debido a re-renderizaciones "legítimas"):
renderizar(<Menú a={1}/>)render(<Menú a={2}/>)
customName
:
A veces, el nombre del componente puede faltar o ser muy inconveniente. Por ejemplo:
conPropsOnChange(conPropsOnChange(conStateHandlers(conPropsOnChange(conEstado(conPropsOnChange(ciclo de vida(conPropsOnChange(conPropsOnChange(soloUpdateForKeys(LoadNamesp ace(Connect(withState(withState(withPropsOnChange(lifecycle(withPropsOnChange(withHandlers(withHandlers(withHandlers(withHandlers(Connect(lifecycle(Menu))))))))))))))))))))))))
Opcionalmente, puede pasar options
como segundo parámetro. Están disponibles las siguientes opciones:
include: [RegExp, ...]
( null
por defecto)
exclude: [RegExp, ...]
( null
por defecto)
trackAllPureComponents: false
trackHooks: true
trackExtraHooks: []
logOwnerReasons: true
logOnDifferentValues: false
hotReloadBufferMs: 500
onlyLogs: false
collapseGroups: false
titleColor
diffNameColor
diffPathColor
notifier: ({Component, displayName, hookName, prevProps, prevState, prevHook, nextProps, nextState, nextHook, reason, options, ownerDataMap}) => void
getAdditionalOwnerData: (element) => {...}
null
) Puede incluir o excluir el seguimiento de componentes por su nombre para mostrar utilizando las opciones include
y exclude
.
Por ejemplo, el siguiente código se utiliza para rastrear todos los renderizados redundantes causados por React-Redux anterior:
por quéDidYouRender(React, {incluye: [/^ConnectFunction/] });
Aviso: excluir tiene prioridad sobre
include
y configurar manualmenteWhyDidYouRenderwhyDidYouRender =
false
) Puede realizar un seguimiento de todos los componentes puros (tanto los componentes React.memo
como React.PureComponent
)
Aviso: puede excluir el seguimiento de cualquier componente específico
whyDidYouRender = false
true
)Puede desactivar el seguimiento de los cambios de ganchos.
Comprender y solucionar problemas de gancho.
[]
)Seguimiento de ganchos personalizados:
WhyDidYouRender(React, { trackExtraHooks: [ // observe que 'useSelector' es una exportación con nombre [ReactRedux, 'useSelector'], ]});
Actualmente existe un problema al reescribir las exportaciones de archivos importados en el paquete web. Hay una solución disponible aquí: #85 - trackExtraHooks no puede establecer la propiedad
true
)Una forma de solucionar los problemas de renderizado es evitar que el propietario del componente vuelva a renderizar.
Esta opción es true
de forma predeterminada y le permite ver los motivos por los cuales se vuelve a renderizar un componente propietario.
false
)Normalmente, solo desea registros sobre la repetición de renderizados de componentes cuando podrían haberse evitado.
Con esta opción, es posible realizar un seguimiento de todos los renderizados.
Por ejemplo:
render(<BigListPureComponent a={1}/>)render(<BigListPureComponent a={2}/>)// solo registrará si usas {logOnDifferentValues: true}
500
)Tiempo en milisegundos para ignorar las actualizaciones después de que se detecta una recarga en caliente.
Cuando se detecta una recarga en caliente, ignoramos todas las actualizaciones de hotReloadBufferMs
para no enviar spam a la consola.
false
) Si no desea utilizar console.group
para agrupar registros, puede imprimirlos como registros simples.
false
)Los registros agrupados se pueden contraer.
'#058'
)'blue'
)'red'
)Controla los colores utilizados en las notificaciones de la consola.
Puede crear un notificador personalizado si el predeterminado no se adapta a sus necesidades.
undefined
)Puede proporcionar una función que recopile datos adicionales del elemento de reacción original. El objeto devuelto por esta función se agregará al propietarioDataMap al que se podrá acceder más adelante dentro de la anulación de la función de notificador.
Si está en producción, es probable que WDYR esté deshabilitado.
Quizás no se realice ningún seguimiento de ningún componente
Consulte los componentes de seguimiento una vez más.
Si solo realiza un seguimiento de componentes puros utilizando trackAllPureComponents: true
, entonces solo realizaría un seguimiento de cualquiera de ellos (React.PureComponent o React.memo), tal vez ninguno de sus componentes sea puro, por lo que ninguno de ellos será rastreado.
Quizás no tengas problemas
Intente causar un problema renderizando temporalmente toda la aplicación dos veces en su punto de entrada:
index.js
:
const HotApp = hot(App);HotApp.whyDidYouRender = true;ReactDOM.render(<HotApp/>, document.getElementById('root'));ReactDOM.render(<HotApp/>, document.getElementById('root') );
Actualmente existe un problema al reescribir las exportaciones de archivos importados en webpack
. Una solución rápida puede ayudar: #85 - trackExtraHooks no puede establecer la propiedad.
connect
HOC está enviando spam a la consola Dado que los polipastos connect
estáticamente, si agrega WDYR al componente interno, también se agrega al componente HOC donde se ejecutan ganchos complejos.
Para solucionar este problema, agregue whyDidYouRender = true
static a un componente después de la conexión:
const SimpleComponent = ({a}) => <div data-testid="foo">{ab}</div>) // no antes de la conexión: // SimpleComponent.whyDidYouRender = true const ConnectedSimpleComponent = connect( state => ({a: state.a}) )(SimpleComponent) // después de la conexión: SimpleComponent.whyDidYouRender = true
Para ver los mapas fuente de la biblioteca, utilice el cargador de mapas fuente.
Inspirado en el siguiente trabajo anterior:
github.com/maicki/why-did-you-update (ya no es público) que tuve la oportunidad de mantener durante algún tiempo.
https://github.com/garbles/why-did-you-update donde se atribuye la idea a una inmersión profunda en la depuración de rendimiento de React.
Esta biblioteca tiene licencia del MIT.