react pasar entre datos comunicacion componentes reactjs

pasar - ReactJS Dos componentes que se comunican.



pasar datos entre componentes react (11)

El mejor enfoque dependerá de cómo planee organizar esos componentes. Algunos ejemplos de escenarios que vienen a la mente en este momento:

  1. <Filters /> es un componente secundario de <List />
  2. Tanto <Filters /> como <List /> son elementos secundarios de un componente principal
  3. <Filters /> y <List /> viven completamente en componentes raíz separados.

Puede haber otros escenarios en los que no estoy pensando. Si el tuyo no encaja dentro de estos, házmelo saber. Aquí hay algunos ejemplos muy aproximados de cómo he manejado los dos primeros escenarios:

Escenario 1

Puede pasar un controlador de <List /> a <Filters /> , que luego se puede llamar en el evento onChange para filtrar la lista con el valor actual.

JSFiddle para # 1 →

/** @jsx React.DOM */ var Filters = React.createClass({ handleFilterChange: function() { var value = this.refs.filterInput.getDOMNode().value; this.props.updateFilter(value); }, render: function() { return <input type="text" ref="filterInput" onChange={this.handleFilterChange} placeholder="Filter" />; } }); var List = React.createClass({ getInitialState: function() { return { listItems: [''Chicago'', ''New York'', ''Tokyo'', ''London'', ''San Francisco'', ''Amsterdam'', ''Hong Kong''], nameFilter: '''' }; }, handleFilterUpdate: function(filterValue) { this.setState({ nameFilter: filterValue }); }, render: function() { var displayedItems = this.state.listItems.filter(function(item) { var match = item.toLowerCase().indexOf(this.state.nameFilter.toLowerCase()); return (match !== -1); }.bind(this)); var content; if (displayedItems.length > 0) { var items = displayedItems.map(function(item) { return <li>{item}</li>; }); content = <ul>{items}</ul> } else { content = <p>No items matching this filter</p>; } return ( <div> <Filters updateFilter={this.handleFilterUpdate} /> <h4>Results</h4> {content} </div> ); } }); React.renderComponent(<List />, document.body);

Escenario # 2

Similar al escenario # 1, pero el componente principal será el que pase la función del controlador a <Filters /> , y pasará la lista filtrada a <List /> . Me gusta más este método, ya que desacopla la <List /> de los <Filters /> .

JSFiddle para # 2 →

/** @jsx React.DOM */ var Filters = React.createClass({ handleFilterChange: function() { var value = this.refs.filterInput.getDOMNode().value; this.props.updateFilter(value); }, render: function() { return <input type="text" ref="filterInput" onChange={this.handleFilterChange} placeholder="Filter" />; } }); var List = React.createClass({ render: function() { var content; if (this.props.items.length > 0) { var items = this.props.items.map(function(item) { return <li>{item}</li>; }); content = <ul>{items}</ul> } else { content = <p>No items matching this filter</p>; } return ( <div className="results"> <h4>Results</h4> {content} </div> ); } }); var ListContainer = React.createClass({ getInitialState: function() { return { listItems: [''Chicago'', ''New York'', ''Tokyo'', ''London'', ''San Francisco'', ''Amsterdam'', ''Hong Kong''], nameFilter: '''' }; }, handleFilterUpdate: function(filterValue) { this.setState({ nameFilter: filterValue }); }, render: function() { var displayedItems = this.state.listItems.filter(function(item) { var match = item.toLowerCase().indexOf(this.state.nameFilter.toLowerCase()); return (match !== -1); }.bind(this)); return ( <div> <Filters updateFilter={this.handleFilterUpdate} /> <List items={displayedItems} /> </div> ); } }); React.renderComponent(<ListContainer />, document.body);

Escenario # 3

Cuando los componentes no pueden comunicarse entre cualquier tipo de relación padre-hijo, la facebook.github.io/react/tips/… .

Acabo de empezar con ReactJS y estoy un poco atascado en un problema que tengo.

Mi aplicación es esencialmente una lista con filtros y un botón para cambiar el diseño. En este momento estoy usando tres componentes: <list /> , < Filters /> y <TopBar /> , ahora obviamente cuando cambio la configuración en < Filters /> quiero activar algún método en <list /> para actualizar mi ver.

¿Cómo puedo hacer que esos 3 componentes interactúen entre sí, o necesito algún tipo de modelo de datos global en el que pueda realizar cambios?


Esta es la forma en que manejé esto.
Digamos que tiene un <select> para el mes y un <select> para el día . El número de días depende del mes seleccionado.

Ambas listas son propiedad de un tercer objeto, el panel izquierdo. Ambos <seleccionar> también son hijos del panel izquierdo <div>
Es un juego con las devoluciones de llamada y los controladores en el componente LeftPanel .

Para probarlo, simplemente copie el código en dos archivos separados y ejecute el archivo index.html . Luego seleccione un mes y vea cómo cambia la cantidad de días.

fechas.js

/** @jsx React.DOM */ var monthsLength = [0,31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; var MONTHS_ARR = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]; var DayNumber = React.createClass({ render: function() { return ( <option value={this.props.dayNum}>{this.props.dayNum}</option> ); } }); var DaysList = React.createClass({ getInitialState: function() { return {numOfDays: 30}; }, handleMonthUpdate: function(newMonthix) { this.state.numOfDays = monthsLength[newMonthix]; console.log("Setting days to " + monthsLength[newMonthix] + " month = " + newMonthix); this.forceUpdate(); }, handleDaySelection: function(evt) { this.props.dateHandler(evt.target.value); }, componentDidMount: function() { this.props.readyCallback(this.handleMonthUpdate) }, render: function() { var dayNodes = []; for (i = 1; i <= this.state.numOfDays; i++) { dayNodes = dayNodes.concat([<DayNumber dayNum={i} />]); } return ( <select id={this.props.id} onChange = {this.handleDaySelection}> <option value="" disabled defaultValue>Day</option> {dayNodes} </select> ); } }); var Month = React.createClass({ render: function() { return ( <option value={this.props.monthIx}>{this.props.month}</option> ); } }); var MonthsList = React.createClass({ handleUpdate: function(evt) { console.log("Local handler:" + this.props.id + " VAL= " + evt.target.value); this.props.dateHandler(evt.target.value); return false; }, render: function() { var monthIx = 0; var monthNodes = this.props.data.map(function (month) { monthIx++; return ( <Month month={month} monthIx={monthIx} /> ); }); return ( <select id = {this.props.id} onChange = {this.handleUpdate}> <option value="" disabled defaultValue>Month</option> {monthNodes} </select> ); } }); var LeftPanel = React.createClass({ dayRefresh: function(newMonth) { // Nothing - will be replaced }, daysReady: function(refreshCallback) { console.log("Regisering days list"); this.dayRefresh = refreshCallback; }, handleMonthChange: function(monthIx) { console.log("New month"); this.dayRefresh(monthIx); }, handleDayChange: function(dayIx) { console.log("New DAY: " + dayIx); }, render: function() { return( <div id="orderDetails"> <DaysList id="dayPicker" dateHandler={this.handleDayChange} readyCallback = {this.daysReady} /> <MonthsList data={MONTHS_ARR} id="monthPicker" dateHandler={this.handleMonthChange} /> </div> ); } }); React.renderComponent( <LeftPanel />, document.getElementById(''leftPanel'') );

Y el HTML para ejecutar el componente del panel izquierdo index.html

<!DOCTYPE html> <html> <head> <title>Dates</title> <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script> <script src="//fb.me/react-0.11.1.js"></script> <script src="//fb.me/JSXTransformer-0.11.1.js"></script> </head> <style> #dayPicker { position: relative; top: 97px; left: 20px; width: 60px; height: 17px; } #monthPicker { position: relative; top: 97px; left: 22px; width: 95px; height: 17px; } select { font-size: 11px; } </style> <body> <div id="leftPanel"> </div> <script type="text/jsx" src="dates.js"></script> </body> </html>


Existe tal posibilidad, incluso si no son una relación padre-hijo, y eso es Flux. Hay una implementación bastante buena (para mí personalmente) para la llamada Alt.JS (con Alt-Container).

Por ejemplo, puede tener la barra lateral que depende de lo que se establece en los detalles del componente. La barra lateral de componentes está conectada con SidebarActions y SidebarStore, mientras que Details es DetailsActions y DetailsStore.

Podrías usar entonces AltContainer así

<AltContainer stores={{ SidebarStore: SidebarStore }}> <Sidebar/> </AltContainer> {this.props.content}

Lo que mantendría las tiendas (bueno, yo podría usar "tienda" en lugar de "tiendas" prop). Ahora, {this.props.content} PUEDE SER Detalles dependiendo de la ruta. Digamos que / Detalles nos redirigen a esa vista. Los detalles tendrían, por ejemplo, una casilla de verificación que cambiaría el elemento de la barra lateral de X a Y si se marcaría.

Técnicamente no hay relación entre ellos y sería difícil hacerlo sin flujo. PERO CON ESO es bastante fácil.

Ahora vamos a DetailsActions. Allí crearemos

class SiteActions { constructor() { this.generateActions( ''setSiteComponentStore'' ); } setSiteComponent(value) { this.dispatch({value: value}); } }

y detalles de la tienda

class SiteStore { constructor() { this.siteComponents = { Prop: true }; this.bindListeners({ setSiteComponent: SidebarActions.COMPONENT_STATUS_CHANGED }) } setSiteComponent(data) { this.siteComponents.Prop = data.value; } }

Y ahora, este es el lugar donde comienza la magia.

Como puede ver, hay un bindListener a SidebarActions.ComponentStatusChanged que se utilizará SI se usará setSiteComponent.

ahora en SidebarActions

componentStatusChanged(value){ this.dispatch({value: value}); }

Tenemos tal cosa. Se despachará ese objeto en la llamada. Y se llamará si se usará setSiteComponent en la tienda (que puede usar en componentes, por ejemplo, durante el cambio en el botón o lo que sea)

Ahora en SidebarStore tendremos

constructor() { this.structures = []; this.bindListeners({ componentStatusChanged: SidebarActions.COMPONENT_STATUS_CHANGED }) } componentStatusChanged(data) { this.waitFor(DetailsStore); _.findWhere(this.structures[0].elem, {title: ''Example''}).enabled = data.value; }

Ahora, aquí puede ver, que esperará a DetailsStore. Qué significa eso? más o menos significa que este método debe esperar a que DetailsStor se actualice antes de que pueda actualizarse.

tl; dr One Store está escuchando los métodos en una tienda, y activará una acción desde la acción del componente, que actualizará su propia tienda.

Espero que te pueda ayudar de alguna manera.


Existen múltiples formas de hacer que los componentes se comuniquen. Algunos pueden ser adecuados para su caso de uso. Aquí hay una lista de algunos que he encontrado útiles para saber.

Reaccionar

Comunicación directa padre / hijo

const Child = ({fromChildToParentCallback}) => ( <div onClick={() => fromChildToParentCallback(42)}> Click me </div> ); class Parent extends React.Component { receiveChildValue = (value) => { console.log("Parent received value from child: " + value); // value is 42 }; render() { return ( <Child fromChildToParentCallback={this.receiveChildValue}/> ) } }

Aquí el componente hijo llamará a una devolución de llamada proporcionada por el padre con un valor, y el padre podrá obtener el valor proporcionado por el hijo en el padre.

Si crea una característica / página de su aplicación, es mejor tener un solo padre que administre las devoluciones de llamada / estado (también llamado container o smart component ), y que todos los niños sean apátridas, solo que informen las cosas al padre. De esta manera, puede "compartir" fácilmente el estado del padre con cualquier niño que lo necesite.

Contexto

React Context permite mantener el estado en la raíz de la jerarquía de sus componentes y ser capaz de inyectar este estado fácilmente en componentes muy profundamente anidados, sin la molestia de tener que transmitir apoyos a todos los componentes intermedios.

Hasta ahora, el contexto era una característica experimental, pero una nueva API está disponible en React 16.3.

const AppContext = React.createContext(null) class App extends React.Component { render() { return ( <AppContext.Provider value={{language: "en",userId: 42}}> <div> ... <SomeDeeplyNestedComponent/> ... </div> </AppContext.Provider> ) } }; const SomeDeeplyNestedComponent = () => ( <AppContext.Consumer> {({language}) => <div>App language is currently {language}</div>} </AppContext.Consumer> );

El consumidor está utilizando el patrón de función prop prop / children

Revisa esta publicación del blog para más detalles.

Antes de React 16.3, recomendaría usar react-broadcast que ofrece una API bastante similar, y usa la API de contexto anterior.

Portales

Use un portal cuando desee mantener los 2 componentes juntos para hacer que se comuniquen con funciones simples, como en los padres / hijos normales, pero no quiere que estos 2 componentes tengan una relación padre / hijo en el DOM, porque de las restricciones visuales / CSS que implica (como el índice z, la opacidad ...).

En este caso puedes usar un "portal". Existen diferentes bibliotecas de reactivos que usan portals , que generalmente se usan para modals , ventanas emergentes, información sobre herramientas ...

Considera lo siguiente:

<div className="a"> a content <Portal target="body"> <div className="b"> b content </div> </Portal> </div>

Podría producir el siguiente DOM cuando se representa dentro de reactAppContainer :

<body> <div id="reactAppContainer"> <div className="a"> a content </div> </div> <div className="b"> b content </div> </body>

Más detalles aquí

Ranuras

Usted define una ranura en algún lugar, y luego llena la ranura desde otro lugar de su árbol de procesamiento.

import { Slot, Fill } from ''react-slot-fill''; const Toolbar = (props) => <div> <Slot name="ToolbarContent" /> </div> export default Toolbar; export const FillToolbar = ({children}) => <Fill name="ToolbarContent"> {children} </Fill>

Esto es un poco similar a los portales, excepto que el contenido relleno se representará en una ranura que usted defina, mientras que los portales generalmente representan un nuevo nodo dom (a menudo, hijos de document.body)

Compruebe la biblioteca de react-slot-fill

Bus de eventos

Como se indica en la facebook.github.io/react/tips/… React:

Para la comunicación entre dos componentes que no tienen una relación padre-hijo, puede configurar su propio sistema de eventos global. Suscríbase a eventos en componentDidMount (), cancele la suscripción a componentWillUnmount () y llame a setState () cuando reciba un evento.

Hay muchas cosas que puede utilizar para configurar un bus de eventos. Simplemente puede crear una variedad de oyentes, y en la publicación del evento, todos los oyentes recibirán el evento. O puedes usar algo como EventEmitter o PostalJs

Flujo

Flux es básicamente un bus de eventos, excepto que los receptores de eventos son tiendas. Esto es similar al sistema de bus de eventos básico, excepto que el estado se administra fuera de React

La implementación original de Flux parece un intento de realizar un abastecimiento de eventos de una manera pirateada.

Redux es para mí la implementación de Flux que está más cerca de la fuente de eventos, un beneficio de muchas de las ventajas de fuentes de eventos como la capacidad de viajar en el tiempo. No está estrictamente vinculado a React y también se puede utilizar con otras bibliotecas de vista funcionales.

El video tutorial de Egghead''s Redux es realmente bueno y explica cómo funciona internamente (realmente es simple).

Cursores

Los cursores provienen de ClojureScript/Om y se utilizan ampliamente en los proyectos React. Permiten administrar el estado fuera de React y permiten que múltiples componentes tengan acceso de lectura / escritura a la misma parte del estado, sin necesidad de saber nada sobre el árbol de componentes.

Existen muchas implementaciones, incluyendo ImmutableJS , React-cursors y Omniscient

Edición 2016 : parece que la gente está de acuerdo en que los cursores funcionan bien para aplicaciones más pequeñas, pero no se ajusta bien en aplicaciones complejas. Om Next ya no tiene cursores (mientras que Om introdujo el concepto inicialmente)

Arquitectura olmo

La arquitectura Elm es una arquitectura propuesta para ser utilizada por el lenguaje Elm . Incluso si Elm no es ReactJS, la arquitectura de Elm también se puede hacer en React.

Dan Abramov, el autor de Redux, hizo una implementation de la arquitectura Elm usando React.

Tanto Redux como Elm son realmente geniales y tienden a potenciar los conceptos de fuente de eventos en la interfaz, permitiendo tanto la depuración de viajes en el tiempo, deshacer / rehacer, reproducir ...

La principal diferencia entre Redux y Elm es que Elm tiende a ser mucho más estricto con respecto a la administración estatal. En Elm, no puede tener un componente de estado local o montar / desmontar ganchos y todos los cambios de DOM deben ser activados por cambios de estado globales. La arquitectura Elm propone un enfoque escalable que permite manejar TODO el estado dentro de un solo objeto inmutable, mientras que Redux propone un enfoque que lo invita a manejar la mayor parte del estado en un solo objeto inmutable.

Si bien el modelo conceptual de Elm es muy elegante y la arquitectura permite escalar bien en aplicaciones grandes, en la práctica puede ser difícil o involucrar más repetitivo para lograr tareas sencillas, como enfocar una entrada después de montarla o integrarla con una biblioteca existente. con una interfaz imperativa (es decir, plugin JQuery). Tema relacionado .

Además, la arquitectura Elm involucra más repetición de código. No es tan detallado o complicado de escribir, pero creo que la arquitectura Elm es más adecuada para los lenguajes tipificados estáticamente.

FRP

Las bibliotecas como RxJS, BaconJS o Kefir se pueden usar para producir flujos de FRP para manejar la comunicación entre componentes.

Puedes probar por ejemplo Rx-React

Creo que usar estas libretas es muy similar a usar lo que ofrece el lenguaje ELM con signals .

CycleJS framework CycleJS no usa ReactJS pero usa vdom . Comparte muchas similitudes con la arquitectura Elm (pero es más fácil de usar en la vida real porque permite los ganchos de vdom) y usa RxJs ampliamente en lugar de funciones, y puede ser una buena fuente de inspiración si quieres usar FRP con Reaccionar. Los videos de CycleJs Egghead son agradables para entender cómo funciona.

CSP

Los CSP (procesos secuenciales de comunicación) son actualmente populares (principalmente debido a Go / goroutines y core.async / ClojureScript) pero puede usarlos también en javascript con JS-CSP .

James Long ha hecho un video explica cómo se puede usar con React.

Sagas

Una saga es un concepto de fondo que proviene del mundo DDD / EventSourcing / CQRS, también llamado "administrador de procesos". Está siendo popularizado por el proyecto redux-saga , principalmente como un reemplazo de redux-thunk para el manejo de efectos secundarios (es decir, llamadas a API, etc.). La mayoría de las personas actualmente piensan que solo sirve para efectos secundarios, pero en realidad es más sobre el desacoplamiento de componentes.

Es más un complemento para una arquitectura de Flux (o Redux) que un sistema de comunicación totalmente nuevo, porque la saga emite acciones de Flux al final. La idea es que si tiene widget1 y widget2, y desea que se desacoplen, no puede disparar la acción dirigida a widget2 desde widget1. Por lo tanto, hace que widget1 solo active acciones dirigidas a sí mismo, y la saga es un "proceso en segundo plano" que escucha las acciones de widget1, y puede enviar acciones dirigidas a widget2. La saga es el punto de acoplamiento entre los 2 widgets, pero los widgets permanecen desacoplados.

Si te interesa mira mi respuesta aquí.

Conclusión

Si desea ver un ejemplo de la misma pequeña aplicación que utiliza estos estilos diferentes, verifique las ramas de este repository .

No sé cuál es la mejor opción a largo plazo, pero realmente me gusta cómo Flux se parece a la fuente de eventos.

Si no conoce los conceptos de fuentes de eventos, eche un vistazo a este blog muy pedagógico: convertir la base de datos al revés con Apache Samza , es una lectura obligatoria para comprender por qué Flux es bueno (pero esto también podría aplicarse a FRP). )

Creo que la comunidad está de acuerdo en que la implementación de Flux más prometedora es Redux , que permitirá progresivamente una experiencia de desarrollador muy productiva gracias a la recarga en caliente. Impresionante codificación en vivo del video Inventing on Principle de Bret Victor es posible!


Extendiendo la respuesta de @MichaelLaCroix cuando un escenario es que los componentes no pueden comunicarse entre cualquier tipo de relación padre-hijo, la documentación recomienda configurar un sistema de eventos global.

En el caso de <Filters /> y <TopBar /> no tienen ninguna de las relaciones anteriores, se podría usar un simple emisor global como este:

componentDidMount - Suscribirse al evento

componentWillUnmount - Anular la suscripción del evento

Código React.js y EventSystem

EventSystem.js

class EventSystem{ constructor() { this.queue = {}; this.maxNamespaceSize = 50; } publish(/** namespace **/ /** arguments **/) { if(arguments.length < 1) { throw "Invalid namespace to publish"; } var namespace = arguments[0]; var queue = this.queue[namespace]; if (typeof queue === ''undefined'' || queue.length < 1) { console.log(''did not find queue for %s'', namespace); return false; } var valueArgs = Array.prototype.slice.call(arguments); valueArgs.shift(); // remove namespace value from value args queue.forEach(function(callback) { callback.apply(null, valueArgs); }); return true; } subscribe(/** namespace **/ /** callback **/) { const namespace = arguments[0]; if(!namespace) throw "Invalid namespace"; const callback = arguments[arguments.length - 1]; if(typeof callback !== ''function'') throw "Invalid callback method"; if (typeof this.queue[namespace] === ''undefined'') { this.queue[namespace] = []; } const queue = this.queue[namespace]; if(queue.length === this.maxNamespaceSize) { console.warn(''Shifting first element in queue: `%s` since it reached max namespace queue count : %d'', namespace, this.maxNamespaceSize); queue.shift(); } // Check if this callback already exists for this namespace for(var i = 0; i < queue.length; i++) { if(queue[i] === callback) { throw ("The exact same callback exists on this namespace: " + namespace); } } this.queue[namespace].push(callback); return [namespace, callback]; } unsubscribe(/** array or topic, method **/) { let namespace; let callback; if(arguments.length === 1) { let arg = arguments[0]; if(!arg || !Array.isArray(arg)) throw "Unsubscribe argument must be an array"; namespace = arg[0]; callback = arg[1]; } else if(arguments.length === 2) { namespace = arguments[0]; callback = arguments[1]; } if(!namespace || typeof callback !== ''function'') throw "Namespace must exist or callback must be a function"; const queue = this.queue[namespace]; if(queue) { for(var i = 0; i < queue.length; i++) { if(queue[i] === callback) { queue.splice(i, 1); // only unique callbacks can be pushed to same namespace queue return; } } } } setNamespaceSize(size) { if(!this.isNumber(size)) throw "Queue size must be a number"; this.maxNamespaceSize = size; return true; } isNumber(n) { return !isNaN(parseFloat(n)) && isFinite(n); } }

NotificationComponent.js

class NotificationComponent extends React.Component { getInitialState() { return { // optional. see alternative below subscriber: null }; } errorHandler() { const topic = arguments[0]; const label = arguments[1]; console.log(''Topic %s label %s'', topic, label); } componentDidMount() { var subscriber = EventSystem.subscribe(''error.http'', this.errorHandler); this.state.subscriber = subscriber; } componentWillUnmount() { EventSystem.unsubscribe(''error.http'', this.errorHandler); // alternatively // EventSystem.unsubscribe(this.state.subscriber); } render() { } }


Si desea explorar las opciones de comunicación entre componentes y siente que se está volviendo cada vez más difícil, entonces podría considerar adoptar un buen patrón de diseño: Flux .

Es simplemente una colección de reglas que define cómo almacenar y mutar el estado de toda la aplicación, y usar ese estado para representar componentes.

Hay muchas implementaciones de Flux, y Flux es una de ellas. Aunque se considera el que contiene la mayoría de los códigos de repetición, es más fácil de entender, ya que la mayoría de las cosas son explícitas.

Algunas de las otras alternativas son flummox fluxxor fluxible y Redux .


Una vez estuve donde estás ahora, como principiante a veces te sientes fuera de lugar en la forma en que reaccionas de esta manera. Voy a tratar de abordar de la misma manera que lo pienso ahora mismo.

Los estados son la piedra angular de la comunicación.

Por lo general, en lo que se refiere a la forma en que modifica los estados de este componente, en su caso, señala tres componentes.

<List /> : que probablemente mostrará una lista de elementos dependiendo de un filtro <Filters /> : Opciones de filtro que alterarán sus datos. <TopBar /> : Lista de opciones.

Para orquestar toda esta interacción, va a necesitar un componente más alto, llamémoslo App, que transmitirá acciones y datos a cada uno de estos componentes para que, por ejemplo, pueda verse así.

<div> <List items={this.state.filteredItems}/> <Filter filter={this.state.filter} setFilter={setFilter}/> </div>

Por lo tanto, cuando se llama a setFilter , afectará a setFilter y volverá a generar ambos componentes ;. En caso de que esto no esté del todo claro, le hice un ejemplo con la casilla de verificación que puede verificar en un solo archivo:

import React, {Component} from ''react''; import {render} from ''react-dom''; const Person = ({person, setForDelete}) => ( <div> <input type="checkbox" name="person" checked={person.checked} onChange={setForDelete.bind(this, person)} /> {person.name} </div> ); class PeopleList extends Component { render() { return( <div> {this.props.people.map((person, i) => { return <Person key={i} person={person} setForDelete={this.props.setForDelete} />; })} <div onClick={this.props.deleteRecords}>Delete Selected Records</div> </div> ); } } // end class class App extends React.Component { constructor(props) { super(props) this.state = {people:[{id:1, name:''Cesar'', checked:false},{id:2, name:''Jose'', checked:false},{id:3, name:''Marbel'', checked:false}]} } deleteRecords() { const people = this.state.people.filter(p => !p.checked); this.setState({people}); } setForDelete(person) { const checked = !person.checked; const people = this.state.people.map((p)=>{ if(p.id === person.id) return {name:person.name, checked}; return p; }); this.setState({people}); } render () { return <PeopleList people={this.state.people} deleteRecords={this.deleteRecords.bind(this)} setForDelete={this.setForDelete.bind(this)}/>; } } render(<App/>, document.getElementById(''app''));


Vi que la pregunta ya está respondida, pero si desea obtener más información, hay un total de 3 casos de comunicación entre componentes :

  • Caso 1: Comunicación padre a hijo.
  • Caso 2: Comunicación niño a padre
  • Caso 3: comunicación de componentes no relacionados (cualquier componente a cualquier componente)

De acuerdo, hay algunas formas de hacerlo, pero quiero concentrarme exclusivamente en el uso de la tienda usando Redux, lo que hace su vida mucho más fácil para estas situaciones, en lugar de darle una solución rápida solo para este caso, el uso de React puro terminará en desorden. La gran aplicación real y la comunicación entre los componentes se hacen cada vez más difíciles a medida que la aplicación crece ...

Entonces, ¿qué hace Redux por ti?

Redux es como el almacenamiento local en su aplicación, que puede usarse siempre que necesite datos para ser usados ​​en diferentes lugares de su aplicación ...

Básicamente, la idea de Redux proviene del flujo originalmente, pero con algunos cambios fundamentales, incluido el concepto de tener una fuente de verdad mediante la creación de una sola tienda ...

Mira la gráfica de abajo para ver algunas diferencias entre Flux y Redux ...

Considere aplicar Redux en su aplicación desde el principio si su aplicación necesita comunicación entre Componentes ...

También puede ser útil leer estas palabras de la documentación de Redux para comenzar con:

Como los requisitos para las aplicaciones de una sola página de JavaScript se han vuelto cada vez más complicados, nuestro código debe administrar más estados que nunca . Este estado puede incluir respuestas del servidor y datos almacenados en caché, así como datos creados localmente que aún no se han conservado en el servidor. El estado de la interfaz de usuario también está aumentando en complejidad, ya que necesitamos administrar rutas activas, pestañas seleccionadas, giros, controles de paginación, etc.

Manejar este estado siempre cambiante es difícil. Si un modelo puede actualizar otro modelo, entonces una vista puede actualizar un modelo, que actualiza otro modelo, y esto, a su vez, puede hacer que se actualice otra vista. En algún momento, ya no comprende lo que sucede en su aplicación, ya que ha perdido el control sobre cuándo, por qué y cómo de su estado. Cuando un sistema es opaco y no determinista, es difícil reproducir errores o agregar nuevas funciones.

Como si esto no fuera lo suficientemente malo, considere que los nuevos requisitos se vuelvan comunes en el desarrollo de productos front-end. Como desarrolladores, se espera que manejemos las actualizaciones optimistas, la representación del lado del servidor, la obtención de datos antes de realizar transiciones de ruta, etc. Nos encontramos tratando de manejar una complejidad con la que nunca antes hemos tenido que lidiar, e inevitablemente nos hacemos la pregunta: ¿es hora de rendirse? La respuesta es no.

Esta complejidad es difícil de manejar ya que estamos mezclando dos conceptos que son muy difíciles de razonar para la mente humana: la mutación y la asincronía. Los llamo Mentos y Coca Cola. Ambos pueden ser grandes en la separación, pero juntos crean un desastre. Las bibliotecas como React intentan resolver este problema en la capa de vista eliminando tanto la asincronía como la manipulación directa de DOM. Sin embargo, la gestión del estado de sus datos queda a su cargo. Aquí es donde entra Redux.

Siguiendo los pasos de Flux, CQRS y Event Sourcing , Redux intenta hacer que las mutaciones de estado sean predecibles imponiendo ciertas restricciones sobre cómo y cuándo pueden ocurrir las actualizaciones . Estas restricciones se reflejan en los tres principios de Redux.


Curiosamente nadie mencionó mobx. La idea es similar a redux. Si tengo una parte de los datos a los que se han suscrito múltiples componentes, entonces puedo usar estos datos para controlar múltiples componentes.


El siguiente código me ayuda a configurar la comunicación entre dos hermanos. La configuración se realiza en su padre durante las llamadas render () y componentDidMount (). Se basa en https://reactjs.org/docs/refs-and-the-dom.html Espero que ayude.

class App extends React.Component<IAppProps, IAppState> { private _navigationPanel: NavigationPanel; private _mapPanel: MapPanel; constructor() { super(); this.state = {}; } // `componentDidMount()` is called by ReactJS after `render()` componentDidMount() { // Pass _mapPanel to _navigationPanel // It will allow _navigationPanel to call _mapPanel directly this._navigationPanel.setMapPanel(this._mapPanel); } render() { return ( <div id="appDiv" style={divStyle}> // `ref=` helps to get reference to a child during rendering <NavigationPanel ref={(child) => { this._navigationPanel = child; }} /> <MapPanel ref={(child) => { this._mapPanel = child; }} /> </div> ); } }