El componente principal ( MyList en mi ejemplo) representa una matriz a través de un componente secundario ( MyComponent ). El padre decide cambiar las propiedades en la matriz, ¿cuál es la forma React de activar la reproducción del niño?
Todo lo que se me ocurrió es this.setState({}); en Parent después de ajustar los datos. ¿Es esto un truco o una forma React de activar una actualización?
Violín JS: https://jsfiddle.net/69z2wepo/7601/
var items = [ {id: 1, highlighted: false, text: "item1"}, {id: 2, highlighted: true, text: "item2"}, {id: 3, highlighted: false, text: "item3"}, ]; var MyComponent = React.createClass({ render: function() { return <div className={this.props.highlighted ? 'light-it-up' : ''}>{this.props.text}</div>; } }); var MyList = React.createClass({ toggleHighlight: function() { this.props.items.forEach(function(v){ v.highlighted = !v.highlighted; }); // Children must re-render // IS THIS CORRECT? this.setState({}); }, render: function() { return <div> <button onClick={this.toggleHighlight}>Toggle highlight</button> {this.props.items.map(function(item) { return <MyComponent key={item.id} text={item.text} highlighted={item.highlighted}/>; })} </div>; } }); React.render(<MyList items={items}/>, document.getElementById('container'));El problema aquí es que está almacenando el estado en this.props en lugar de this.state . Dado que este componente está mutando items , items están en estado y deben almacenarse en this.state . (Aquí hay un buen artículo sobre props vs. state ). Esto resuelve su problema de renderizado, porque cuando actualice items llamará a setState , que activará automáticamente una nueva renderización.
Así es como se vería su componente usando estado en lugar de accesorios:
var MyList = React.createClass({ getInitialState: function() { return { items: this.props.initialItems }; }, toggleHighlight: function() { var newItems = this.state.items.map(function (item) { item.highlighted = !item.highlighted; return item; }); this.setState({ items: newItems }); }, render: function() { return ( <div> <button onClick={this.toggleHighlight}>Toggle highlight</button> { this.state.items.map(function(item) { return <MyComponent key={item.id} text={item.text} highlighted={item.highlighted}/>; }) } </div> ); } }); React.render( <MyList initialItems={initialItems}/>, document.getElementById('container') ); Tenga en cuenta que cambié el nombre de items prop a initialItems , porque deja en claro que MyList lo mutará. Esto es recomendado por la documentación .
Puede ver el violín actualizado aquí: https://jsfiddle.net/kxrf5329/
Encontré una buena solución usando el atributo clave para volver a renderizar con React Hook . Si cambiamos la propiedad clave de un componente secundario o alguna parte de React Component, se volverá a procesar por completo. Se usará cuando necesite volver a renderizar una parte de React Component o volver a renderizar un componente secundario. Aquí hay un ejemplo. Volveré a renderizar el componente completo.
import React, { useState, useEffect } from "react"; import { PrEditInput } from "./shared"; const BucketInput = ({ bucketPrice = [], handleBucketsUpdate, mood }) => { const data = Array.isArray(bucketPrice) ? bucketPrice : []; const [state, setState] = useState(Date.now()); useEffect(() => { setState(Date.now()); }, [mood, bucketPrice]); return ( <span key={state}> {data.map((item) => ( <PrEditInput key={item.id} label={item?.bucket?.name} name={item.bucketId} defaultValue={item.price} onChange={handleBucketsUpdate} mood={mood} /> ))} </span> ); }; export default BucketInput;Una opción sencilla para volver a renderizar a un niño es actualizar un atributo clave único cada vez que necesite volver a renderizar.
<ChildComponent key={this.state.updatedKey}/>