Comprensión de React-Redux y mapStateToProps ()

232
Pablo Barría Urenda 2016-07-06 01:42.

Estoy tratando de entender el método de conexión de react-redux y las funciones que toma como parámetros. En particular mapStateToProps().

Según tengo entendido, el valor de retorno de mapStateToPropsserá un objeto derivado del estado (ya que vive en la tienda), cuyas claves se pasarán a su componente de destino (se aplica el componente de conexión) como accesorios.

Esto significa que el estado consumido por su componente objetivo puede tener una estructura muy diferente del estado almacenado en su tienda.

P: ¿Está bien?
P: ¿Es esto esperado?
P: ¿Es esto un anti-patrón?

9 answers

61
Richard Strickland 2017-09-27 04:37.

Q: Is this ok?
A: si

P: Is this expected?
Sí, se espera esto (si está utilizando react-redux).

P: Is this an anti-pattern?
R: No, esto no es un anti-patrón.

Se llama "conectar" su componente o "hacerlo inteligente". Es por diseño.

Le permite desacoplar su componente de su estado un tiempo adicional, lo que aumenta la modularidad de su código. También le permite simplificar el estado de su componente como un subconjunto del estado de su aplicación que, de hecho, le ayuda a cumplir con el patrón Redux.

Piénselo de esta manera: se supone que una tienda contiene el estado completo de su aplicación.
Para aplicaciones grandes, esto podría contener docenas de propiedades anidadas en muchas capas de profundidad.
No querrás cargar con todo eso en cada llamada (caro).

Sin mapStateToPropso sin algún análogo del mismo, estaría tentado de dividir su estado de otra manera para mejorar el rendimiento / simplificar.

121
webdeb 2016-07-06 03:46.

Si es correcto. Es solo una función auxiliar para tener una forma más sencilla de acceder a las propiedades de su estado

Imagina que tienes una postsclave en tu aplicaciónstate.posts

state.posts //
/*    
{
  currentPostId: "",
  isFetching: false,
  allPosts: {}
}
*/

Y componente Posts

De forma predeterminada connect()(Posts), todos los accesorios de estado estarán disponibles para el componente conectado

const Posts = ({posts}) => (
  <div>
    {/* access posts.isFetching, access posts.allPosts */}
  </div> 
)

Ahora, cuando asigna el state.postscomponente a su componente, se vuelve un poco mejor

const Posts = ({isFetching, allPosts}) => (
  <div>
    {/* access isFetching, allPosts directly */}
  </div> 
)

connect(
  state => state.posts
)(Posts)

mapDispatchToProps

normalmente tienes que escribir dispatch(anActionCreator())

con bindActionCreatorspuedes hacerlo también más fácilmente como

connect(
  state => state.posts,
  dispatch => bindActionCreators({fetchPosts, deletePost}, dispatch)
)(Posts)

Ahora puedes usarlo en tu Componente

const Posts = ({isFetching, allPosts, fetchPosts, deletePost }) => (
  <div>
    <button onClick={() => fetchPosts()} />Fetch posts</button>
    {/* access isFetching, allPosts directly */}
  </div> 
)

Actualización sobre actionCreators ..

Un ejemplo de actionCreator: deletePost

const deletePostAction = (id) => ({
  action: 'DELETE_POST',
  payload: { id },
})

Entonces, bindActionCreatorssolo tomará sus acciones, las envolverá en una dispatchllamada. (No leí el código fuente de redux, pero la implementación podría verse así:

const bindActionCreators = (actions, dispatch) => {
  return Object.keys(actions).reduce(actionsMap, actionNameInProps => {
    actionsMap[actionNameInProps] = (...args) => dispatch(actions[actionNameInProps].call(null, ...args))
    return actionsMap;
  }, {})
}
40
Mohamed Mellouki 2016-07-06 02:40.

Tienes la primera parte bien:

Yes mapStateToPropstiene el estado Store como argumento / parámetro (proporcionado por react-redux::connect) y se usa para vincular el componente con cierta parte del estado de la tienda.

Al vincular me refiero a que el objeto devuelto por mapStateToPropsse proporcionará en el momento de la construcción como accesorios y cualquier cambio posterior estará disponible a través de componentWillReceiveProps.

Si conoce el patrón de diseño de Observer, es exactamente eso o una pequeña variación de él.

Un ejemplo ayudaría a aclarar las cosas:

import React, {
    Component,
} from 'react-native';

class ItemsContainer extends Component {
    constructor(props) {
        super(props);

        this.state = {
            items: props.items, //provided by [email protected]
            filteredItems: this.filterItems(props.items, props.filters),
        };
    }

    componentWillReceiveProps(nextProps) {
        this.setState({
            filteredItems: this.filterItems(this.state.items, nextProps.filters),
        });
    }

    filterItems = (items, filters) => { /* return filtered list */ }

    render() {
        return (
            <View>
                // display the filtered items
            </View>
        );
    }
}

module.exports = connect(
    //mapStateToProps,
    (state) => ({
        items: state.App.Items.List,
        filters: state.App.Items.Filters,
        //the State.App & state.App.Items.List/Filters are reducers used as an example.
    })
    // mapDispatchToProps,  that's another subject
)(ItemsContainer);

Puede haber otro componente de reacción llamado itemsFiltersque maneje la pantalla y persista el estado del filtro en el estado de Redux Store, el componente de demostración está "escuchando" o "suscrito" a los filtros de estado de Redux Store, por lo que cada vez que los filtros almacenan cambios de estado (con la ayuda de filtersComponent) reaccionar -redux detecta que hubo un cambio y notifica o "publica" todos los componentes que están escuchando / suscritos enviando los cambios a sus componentWillReceivePropsque, en este ejemplo, activarán un nuevo filtro de los elementos y actualizarán la pantalla debido al hecho de que el estado de reacción ha cambiado .

Avíseme si el ejemplo es confuso o no es lo suficientemente claro como para proporcionar una mejor explicación.

En cuanto a: Esto significa que el estado consumido por su componente objetivo puede tener una estructura muy diferente del estado almacenado en su tienda.

No recibí la pregunta, ¡pero sé que el estado de reacción ( this.setState) es totalmente diferente del estado de Redux Store!

El estado de reacción se usa para manejar el rediseño y el comportamiento del componente de reacción. El estado de reacción está contenido en el componente exclusivamente.

El estado de Redux Store es una combinación de estados de reductores de Redux, cada uno es responsable de administrar una pequeña parte de la lógica de la aplicación. ¡Se puede acceder a esos atributos reductores con la ayuda de react-redux::[email protected]cualquier componente! Lo que hace que la aplicación de acceso al estado de la tienda Redux sea amplia, mientras que el estado del componente es exclusivo para sí mismo.

5
Patrick W. McMahon 2017-09-16 09:07.

Este ejemplo de react & redux se basa en el ejemplo de Mohamed Mellouki. Pero valida usando reglas de embellecimiento y pelaje . Tenga en cuenta que definimos nuestros accesorios y métodos de envío utilizando PropTypes para que nuestro compilador no nos grite. Este ejemplo también incluyó algunas líneas de código que faltaban en el ejemplo de Mohamed. Para usar connect, deberá importarlo desde react-redux . Este ejemplo también vincula el método filterItems, lo que evitará problemas de alcance en el componente . Este código fuente se ha formateado automáticamente con JavaScript Prettify .

import React, { Component } from 'react-native';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';

class ItemsContainer extends Component {
  constructor(props) {
    super(props);
    const { items, filters } = props;
    this.state = {
      items,
      filteredItems: filterItems(items, filters),
    };
    this.filterItems = this.filterItems.bind(this);
  }

  componentWillReceiveProps(nextProps) {
    const { itmes } = this.state;
    const { filters } = nextProps;
    this.setState({ filteredItems: filterItems(items, filters) });
  }

  filterItems = (items, filters) => {
    /* return filtered list */
  };

  render() {
    return <View>/*display the filtered items */</View>;
  }
}

/*
define dispatch methods in propTypes so that they are validated.
*/
ItemsContainer.propTypes = {
  items: PropTypes.array.isRequired,
  filters: PropTypes.array.isRequired,
  onMyAction: PropTypes.func.isRequired,
};

/*
map state to props
*/
const mapStateToProps = state => ({
  items: state.App.Items.List,
  filters: state.App.Items.Filters,
});

/*
connect dispatch to props so that you can call the methods from the active props scope.
The defined method `onMyAction` can be called in the scope of the componets props.
*/
const mapDispatchToProps = dispatch => ({
  onMyAction: value => {
    dispatch(() => console.log(`${value}`));
  },
});

/* clean way of setting up the connect. */
export default connect(mapStateToProps, mapDispatchToProps)(ItemsContainer);

Este código de ejemplo es una buena plantilla como punto de partida para su componente.

2
ArunValaven 2017-08-03 20:26.

React-Redux connect se usa para actualizar la tienda para cada acción.

import { connect } from 'react-redux';

const AppContainer = connect(  
  mapStateToProps,
  mapDispatchToProps
)(App);

export default AppContainer;

Se explica de manera muy simple y clara en este blog .

Puede clonar el proyecto github o copiar y pegar el código de ese blog para comprender la conexión de Redux.

1
zloctb 2019-01-12 02:33.

Aquí hay un esquema / texto estándar para describir el comportamiento de mapStateToProps:

(Esta es una implementación muy simplificada de lo que hace un contenedor Redux).

class MyComponentContainer extends Component {
  mapStateToProps(state) {
    // this function is specific to this particular container
    return state.foo.bar;
  }

  render() {
    // This is how you get the current state from Redux,
    // and would be identical, no mater what mapStateToProps does
    const { state } = this.context.store.getState();

    const props = this.mapStateToProps(state);

    return <MyComponent {...this.props} {...props} />;
  }
}

y después

function buildReduxContainer(ChildComponentClass, mapStateToProps) {
  return class Container extends Component {
    render() {
      const { state } = this.context.store.getState();

      const props = mapStateToProps(state);

      return <ChildComponentClass {...this.props} {...props} />;
    }
  }
}
1
coder9833idls 2020-09-09 00:14.

Es un concepto simple. Redux crea un objeto de estado ubicuo (una tienda) a partir de las acciones en los reductores. Al igual que un componente de React, este estado no tiene que codificarse explícitamente en ningún lugar, pero ayuda a los desarrolladores a ver un objeto de estado predeterminado en el archivo reductor para visualizar lo que está sucediendo. Importa el reductor en el componente para acceder al archivo. Luego, mapStateToProps selecciona solo los pares clave / valor en la tienda que necesita su componente. Piense en ello como Redux creando una versión global de un componente de React

this.state = ({ 
cats = [], 
dogs = []
})

Es imposible cambiar la estructura del estado usando mapStateToProps (). Lo que está haciendo es elegir solo los pares clave / valor de la tienda que el componente necesita y pasar los valores (de una lista de clave / valores en la tienda) a los accesorios (claves locales) en su componente. Haz esto un valor a la vez en una lista. No se pueden producir cambios de estructura en el proceso.

PD: La tienda es un estado local. Los Reductores generalmente también pasan el estado a la base de datos con Action Creators ingresando a la mezcla, pero primero comprenda este concepto simple para esta publicación específica.

PPS Es una buena práctica separar los reductores en archivos separados para cada uno e importar solo el reductor que necesita el componente.

0
Ravi Veliyat 2020-09-01 03:28.

Me gustaría reestructurar la declaración que mencionaste, que es:

Esto significa que el estado consumido por su componente objetivo puede tener una estructura muy diferente del estado almacenado en su tienda.

Puede decir que el estado consumido por su componente de destino tiene una pequeña parte del estado que se almacena en la tienda redux. En otras palabras, el estado consumido por su componente sería el subconjunto del estado de la tienda redux.

En lo que respecta a la comprensión del método connect (), ¡es bastante simple! El método connect () tiene el poder de agregar nuevos accesorios a su componente e incluso anular los accesorios existentes. Es a través de este método de conexión que también podemos acceder al estado de la tienda redux que nos envía el Proveedor. Una combinación de las cuales funciona a su favor y puede agregar el estado de su tienda redux a los accesorios de su componente.

Arriba hay algo de teoría y le sugiero que mire este video una vez para comprender mejor la sintaxis.

0
Mohan Krishna Sai 2020-09-24 20:35.

Sí, usted puede hacer esto. También puede procesar el estado y devolver el objeto.

function mapStateToProps(state){  
  let completed = someFunction (state);
   return {
     completed : completed,  
   }
}
 

Esto sería útil si desea cambiar la lógica relacionada con el estado de la función de renderizado a fuera de ella.

Related questions

MORE COOL STUFF

La estrella de HGTV, Christina Hall, revela que tiene 'envenenamiento por mercurio y plomo' probablemente por voltear 'casas asquerosas'

La estrella de HGTV, Christina Hall, revela que tiene 'envenenamiento por mercurio y plomo' probablemente por voltear 'casas asquerosas'

La estrella de HGTV, Christina Hall, revela que le diagnosticaron envenenamiento por mercurio y plomo, probablemente debido a su trabajo como manipuladora de casas.

La estrella de 'Love Is Blind' Brennon Lemieux responde a los cargos de violencia doméstica

La estrella de 'Love Is Blind' Brennon Lemieux responde a los cargos de violencia doméstica

Recientemente salió a la luz un informe policial que acusa a la estrella de 'Love Is Blind', Brennon, de violencia doméstica. Ahora, Brennon ha respondido a los reclamos.

Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia Judd en un momento festivo de pánico

Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia Judd en un momento festivo de pánico

Conozca cómo Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia mientras organizaba la primera celebración de Acción de Gracias desde que murió su madre, Naomi Judd.

Experto en lenguaje corporal explica los 'paralelos' entre Kate Middleton y la princesa Diana

Experto en lenguaje corporal explica los 'paralelos' entre Kate Middleton y la princesa Diana

Descubra por qué un destacado experto en lenguaje corporal cree que es fácil trazar "tales paralelismos" entre la princesa Kate Middleton y la princesa Diana.

Los láseres arrojan luz sobre por qué necesita cerrar la tapa antes de descargar

Los láseres arrojan luz sobre por qué necesita cerrar la tapa antes de descargar

Los inodoros arrojan columnas de aerosol invisibles con cada descarga. ¿Como sabemos? La prueba fue capturada por láseres de alta potencia.

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

¿Caduca el repelente de insectos?

¿Caduca el repelente de insectos?

¿Sigue siendo efectivo ese lote de repelente de insectos que te quedó del verano pasado? Si es así, ¿por cuánto tiempo?

Actualice a un Sonicare por tan solo $ 30

Actualice a un Sonicare por tan solo $ 30

¿Quiere probar un cepillo de dientes Sonicare sin gastar mucho dinero en uno de sus modelos favoritos de gama alta? Puede comprar un kit de la Serie 2 o Serie 3 por tan solo $ 30 hoy en Amazon. Haga clic aquí para ver la lista completa de modelos elegibles y tenga en cuenta que se descontarán $ 10 adicionales en su carrito.

Ponle una tapa. En realidad, ponle una tapa a todo. Consigue 12 tapas de cocina elásticas de silicona por $14. [Exclusivo]

Ponle una tapa. En realidad, ponle una tapa a todo. Consigue 12 tapas de cocina elásticas de silicona por $14. [Exclusivo]

Tapas elásticas de silicona de Tomorrow's Kitchen, paquete de 12 | $14 | Amazonas | Código promocional 20OFFKINJALids son básicamente los calcetines de la cocina; siempre perdiéndose, dejando contenedores huérfanos que nunca podrán volver a cerrarse. Pero, ¿y si sus tapas pudieran estirarse y adaptarse a todos los recipientes, ollas, sartenes e incluso frutas en rodajas grandes que sobran? Nunca más tendrás que preocuparte por perder esa tapa tan específica.

Cuéntanos tus mejores trucos de Washington, DC

Cuéntanos tus mejores trucos de Washington, DC

Hemos pirateado algunas ciudades industriales en esta columna, como Los Ángeles y Las Vegas. Ahora es el momento de una ciudad militar-industrial-compleja.

Un minorista está eliminando su sección de tallas grandes y mezclando tallas más grandes con todo lo demás

Un minorista está eliminando su sección de tallas grandes y mezclando tallas más grandes con todo lo demás

Un minorista está enlatando su sección de tallas grandes. Pero no están tomando la categoría solo en línea o descontinuándola por completo.

Patinaje artístico de EE. UU. 'frustrado' por falta de decisión final en evento por equipos, pide una decisión justa

Patinaje artístico de EE. UU. 'frustrado' por falta de decisión final en evento por equipos, pide una decisión justa

El equipo está a la espera de las medallas que ganó en los Juegos Olímpicos de Invierno de 2022 en Beijing, ya que se está resolviendo un caso de dopaje que involucra a la patinadora artística rusa Kamila Valieva.

Los compradores de Amazon dicen que duermen 'como un bebé mimado' gracias a estas fundas de almohada de seda que cuestan tan solo $ 10

Los compradores de Amazon dicen que duermen 'como un bebé mimado' gracias a estas fundas de almohada de seda que cuestan tan solo $ 10

Miles de compradores de Amazon recomiendan la funda de almohada de seda Mulberry, y está a la venta en este momento. La funda de almohada de seda viene en varios colores y ayuda a mantener el cabello suave y la piel clara. Compre las fundas de almohada de seda mientras tienen hasta un 46 por ciento de descuento en Amazon

Se busca al corredor de los Bengals Joe Mixon por orden de arresto emitida por presuntamente apuntar con un arma de fuego a una mujer

Se busca al corredor de los Bengals Joe Mixon por orden de arresto emitida por presuntamente apuntar con un arma de fuego a una mujer

El jueves se presentó una denuncia de delito menor amenazante agravado contra Joe Mixon.

Profesor de la Universidad de Purdue arrestado por presuntamente traficar metanfetamina y proponer favores sexuales a mujeres

Profesor de la Universidad de Purdue arrestado por presuntamente traficar metanfetamina y proponer favores sexuales a mujeres

El Departamento de Policía de Lafayette comenzó a investigar a un profesor de la Universidad de Purdue en diciembre después de recibir varias denuncias de un "hombre sospechoso que se acercaba a una mujer".

Concept Drift: el mundo está cambiando demasiado rápido para la IA

Concept Drift: el mundo está cambiando demasiado rápido para la IA

Al igual que el mundo que nos rodea, el lenguaje siempre está cambiando. Mientras que en eras anteriores los cambios en el idioma ocurrían durante años o incluso décadas, ahora pueden ocurrir en cuestión de días o incluso horas.

India me está pateando el culo

India me está pateando el culo

Estoy de vuelta por primera vez en seis años. No puedo decirte cuánto tiempo he estado esperando esto.

ℝ

“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.

¿Merrick Garland le ha fallado a Estados Unidos?

Es más de la mitad de la presidencia de Biden. ¿Qué está esperando Merrick Garland?

¿Merrick Garland le ha fallado a Estados Unidos?

Creo, un poco tarde en la vida, en dar oportunidades a la gente. Generosamente.

Language