react props ownprops mapstatetoprops mapstate ejemplo javascript redux react-redux

javascript - props - react-router-redux



Comprender React-Redux y mapStateToProps() (7)

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 mapStateToProps será un objeto derivado del estado (como vive en la tienda), cuyas claves se pasarán a su componente de destino (se aplica la conexión del componente) como accesorios.

Esto significa que el estado consumido por su componente de destino puede tener una estructura muy diferente del estado que se almacena en su tienda.

P: ¿Está bien?
P: ¿Se espera esto?
P: ¿Es esto un antipatrón?


Aquí hay un esquema / plantilla 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} />; } } }


Este ejemplo de react y redux se basa en el ejemplo de Mohamed Mellouki. Pero valida usando reglas de prettify y linting . Tenga en cuenta que definimos nuestros accesorios y métodos de dispatch utilizando PropTypes para que nuestro compilador no nos grite. Este ejemplo también incluía algunas líneas de código que faltaban en el ejemplo de Mohamed. Para usar connect necesitará importarlo desde redux . Este ejemplo también binds el método filterItems, esto evitará problemas de scope en el component . 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.


P: Is this ok?
A: si

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

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

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

Le permite desacoplar su componente de su estado una vez más, 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, lo ayuda a cumplir con el patrón de Redux.

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

Sin mapStateToProps o algún análogo de los mismos, estaría tentado a dividir su estado de otra manera para mejorar el rendimiento / simplificar.


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

Imagine que tiene una clave de posts en el estado de su aplicación state.posts

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

Y Posts componentes

Por defecto, connect()(Posts) hará que todos los accesorios de estado estén disponibles para el Componente conectado

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

Ahora, cuando state.posts el estado state.posts a su componente, se vuelve un poco más agradable

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

mapDispatchToProps

normalmente tiene que escribir dispatch(anActionCreator())

con bindActionCreators puedes hacerlo también más fácilmente

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, bindActionCreators solo tomará sus acciones, las envolverá en una llamada de dispatch . (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; }, {}) }


Tienes la primera parte correcta:

Sí, mapStateToProps tiene el estado Store como argumento / parámetro (proporcionado por react-redux::connect ) y se usa para vincular el componente con cierta parte del estado store.

Al vincular me refiero al objeto devuelto por mapStateToProps se 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 del mismo.

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 connect@mapStateToProps 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 itemsFilters que maneja la pantalla y persiste 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 los filtersComponent ) react-redux detecta que hubo un cambio y notifica o "publica" todos los componentes de escucha / suscritos enviando los cambios a su componentWillReceiveProps que, en este ejemplo, activará un refiltro de los elementos y actualizará la pantalla debido al hecho de que reaccionan El estado 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 de destino puede tener una estructura muy diferente del estado tal como se almacena en su tienda.

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

El estado de reacción se utiliza para manejar el redibujo y el comportamiento del componente de reacción. El estado de reacción está contenido exclusivamente en el componente.

El estado de Redux Store es una combinación de estados de reductores de Redux, cada uno es responsable de administrar una pequeña porción de la lógica de la aplicación. Se puede acceder a esos atributos reductores con la ayuda de react-redux::connect@mapStateToProps por cualquier componente. Lo que hace que el estado de la tienda Redux sea accesible en toda la aplicación, mientras que el estado del componente es exclusivo para sí mismo.


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

import { connect } from ''react-redux''; const AppContainer = connect( mapStateToProps, mapDispatchToProps )(App); export default AppContainer;

Es muy simple y claramente explicado 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.


import React from ''react''; import {connect} from ''react-redux''; import Userlist from ''./Userlist''; class Userdetails extends React.Component{ render(){ return( <div> <p>Name : <span>{this.props.user.name}</span></p> <p>ID : <span>{this.props.user.id}</span></p> <p>Working : <span>{this.props.user.Working}</span></p> <p>Age : <span>{this.props.user.age}</span></p> </div> ); }

}

function mapStateToProps(state){ *state is your redux-store object* return { user:state.activeUser }

}

export default connect(mapStateToProps)(Userdetails);