w3schools vue tutorial relleno react node instalar gruesas funciones funcion flechas flecha example ejemplos con azul javascript reactjs

javascript - vue - typescript funcion flecha



Cómo evitar las funciones de enlace o flecha en línea dentro del método de representación (4)

¿Cómo evitar esta forma de vinculación dentro del método de renderizado o cuáles son las alternativas de esto?

Si le importa la representación, entonces shouldComponentUpdate y PureComponent son sus amigos y le ayudarán a optimizar la representación.

shouldComponentUpdate extraer el componente "Hijo" del "Padre" y pasar siempre los mismos accesorios e implementar shouldComponentUpdate o usar PureComponent . Lo que queremos es un caso en el que eliminamos a un niño, otros niños no deberían volver a procesarse.

Ejemplo

import React, { Component, PureComponent } from ''react''; import { render } from ''react-dom''; class Product extends PureComponent { render() { const { id, name, onDelete } = this.props; console.log(`<Product id=${id} /> render()`); return ( <li> {id} - {name} <button onClick={() => onDelete(id)}>Delete</button> </li> ); } } class App extends Component { constructor(props) { super(props); this.state = { products: [ { id: 1, name: ''Foo'' }, { id: 2, name: ''Bar'' }, ], }; this.handleDelete = this.handleDelete.bind(this); } handleDelete(productId) { this.setState(prevState => ({ products: prevState.products.filter(product => product.id !== productId), })); } render() { console.log(`<App /> render()`); return ( <div> <h1>Products</h1> <ul> { this.state.products.map(product => ( <Product key={product.id} onDelete={this.handleDelete} {...product} /> )) } </ul> </div> ); } } render(<App />, document.getElementById(''root''));

Demostración: https://codesandbox.io/s/99nZGlyZ

Comportamiento esperado

  • <App /> render()
  • <Product id=1... render()
  • <Product id=2... render()

Cuando eliminamos <Product id=2 ... solo se vuelve a procesar <App /> .

  • hacer()

Para ver esos mensajes en la demostración, abra la consola de herramientas de desarrollo.

La misma técnica se utiliza y se describe en el artículo: React is Slow, React is Fast: Optimizing React Apps in Practice de François Zaninotto.

Deberíamos evitar el enlace de métodos dentro del renderizado porque durante el renderizado creará los nuevos métodos en lugar de usar el antiguo, lo que afectará el rendimiento.

Entonces, para los escenarios como este:

<input onChange = { this._handleChange.bind(this) } ...../>

Podemos vincular el método _handleChange en el constructor:

this._handleChange = this._handleChange.bind(this);

O podemos usar la sintaxis del inicializador de propiedades :

_handleChange = () => {....}

Ahora consideremos el caso en el que queremos pasar algún parámetro adicional, digamos en una aplicación de tareas simple, al hacer clic en el elemento, necesito eliminar el elemento de la matriz, para eso necesito pasar el índice del elemento o el nombre de todo en cada Método onClick:

todos.map(el => <div key={el} onClick={this._deleteTodo.bind(this, el)}> {el} </div>)

Por ahora solo asuma que los nombres de tareas son únicos.

Según DOC :

El problema con esta sintaxis es que se crea una devolución de llamada diferente cada vez que se procesa el componente.

Pregunta:

¿Cómo evitar esta forma de vinculación dentro del método de renderizado o cuáles son las alternativas de esto?

Proporcione amablemente cualquier referencia o ejemplo, gracias.


Esta respuesta https://.com/a/45053753/2808062 es definitivamente exhaustiva, pero diría que es mejor resolver este problema mediante la implementación de una shouldComponentUpdate adecuada de shouldComponentUpdate en el componente secundario.

Incluso si los accesorios son exactamente iguales, el siguiente código seguirá representando a los niños a menos que lo impidan en su propio shouldComponentUpdate (podrían heredarlo de PureComponent ):

handleChildClick = itemId => {} render() { return this.props.array.map(itemData => <Child onClick={this.handleChildClick} data={itemData}) }

Prueba: https://jsfiddle.net/69z2wepo/92281/ .

Entonces, para evitar los renders, el componente hijo tiene que implementar shouldComponentUpdate todos modos. Ahora, la única implementación razonable es ignorar completamente onClick independientemente de si ha cambiado:

shouldComponentUpdate(nextProps) { return this.props.array !== nextProps.array; }


Documentation alienta a usar atributos de datos y acceder a ellos desde evt.target.dataset :

_deleteTodo = (evt) => { const elementToDelete = evt.target.dataset.el; this.setState(prevState => ({ todos: prevState.todos.filter(el => el !== elementToDelete) })) } // and from render: todos.map( el => <div key={el} data-el={el} onClick={this._deleteTodo}> {el} </div> )

También note que esto tiene sentido solo cuando tiene problemas de rendimiento:

¿Está bien usar funciones de flecha en los métodos de renderizado?

En términos generales, sí, está bien, y a menudo es la forma más fácil de pasar parámetros a las funciones de devolución de llamada.

Si tiene problemas de rendimiento, por supuesto, ¡optimice!


Primero: una solución simple será crear un componente para el contenido dentro de una función de mapa y pasar los valores como accesorios y cuando llame a la función desde el componente secundario, puede pasar el valor a la función transmitida como accesorios.

Padre

deleteTodo = (val) => { console.log(val) } todos.map(el => <MyComponent val={el} onClick={this.deleteTodo}/> )

MyComponent

class MyComponent extends React.Component { deleteTodo = () => { this.props.onClick(this.props.val); } render() { return <div onClick={this.deleteTodo}> {this.props.val} </div> } }

Fragmento de muestra

class Parent extends React.Component { _deleteTodo = (val) => { console.log(val) } render() { var todos = [''a'', ''b'', ''c'']; return ( <div>{todos.map(el => <MyComponent key={el} val={el} onClick={this._deleteTodo}/> )}</div> ) } } class MyComponent extends React.Component { _deleteTodo = () => { console.log(''here''); this.props.onClick(this.props.val); } render() { return <div onClick={this._deleteTodo}> {this.props.val} </div> } } ReactDOM.render(<Parent/>, document.getElementById(''app''));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="app"></div>

EDITAR:

Segundo: el otro enfoque sería usar memorizar y devolver una función

constructor() { super(); this._deleteTodoListener = _.memoize( this._deleteTodo, (element) => { return element.hashCode(); } ) } _deleteTodo = (element) => { //delete handling here }

y usándolo como

todos.map(el => <div key={el} onClick={this._deleteTodoListener(el)}> {el} </div>)

PD Sin embargo, esta no es la mejor solución y seguirá dando lugar a la creación de múltiples funciones, pero sigue siendo una mejora con respecto al caso inicial.

Tercero: Sin embargo, una solución más apropiada para esto será agregar un attribute al div superior y obtener el valor de un event como

_deleteTodo = (e) => { console.log(e.currentTarget.getAttribute(''data-value'')); } todos.map(el => <div key={el} data-value={el} onClick={this._deleteTodo}> {el} </div>)

Sin embargo, en este caso, los atributos se convierten en cadena utilizando el método toString y, por lo tanto, el objeto se convertirá en [Object Object] y una matriz como ["1" , "2", "3"] como "1, 2, 3"