Comprender React-Redux y mapStateToProps()
Estoy tratando de comprender el método de conexión de reaccionar-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 (tal como se encuentra en la tienda), cuyas claves se pasarán a su componente de destino (al que se aplica la conexión del componente) como accesorios.
Esto significa que el estado consumido por el componente de destino puede tener una estructura muy diferente del estado almacenado en su tienda.
P: ¿Está bien?
P: ¿Se espera esto?
P: ¿Es esto un antipatrón?
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 posts
clave en tu Appstate.posts
state.posts //
/*
{
currentPostId: "",
isFetching: false,
allPosts: {}
}
*/
y componentePosts
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 asignas el state.posts
componente a tu componente, se vuelve un poco mejor.
const Posts = ({isFetching, allPosts}) => (
<div>
{/* access isFetching, allPosts directly */}
</div>
)
connect(
state => state.posts
)(Posts)
mapaDispatchToProps
normalmente tienes que escribirdispatch(anActionCreator())
con bindActionCreators
usted también puede hacerlo 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 creadores de acción...
Un ejemplo de un creador de acciones:deletePost
const deletePostAction = (id) => ({
action: 'DELETE_POST',
payload: { id },
})
Entonces, bindActionCreators
simplemente tomaremos sus acciones y las envolveremos en dispatch
una llamada. (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;
}, {})
}
P: R Is this ok?
: sí
P: Is this expected?
Sí, esto es lo esperado (si está utilizando reaccionar-redux).
P: R Is this an anti-pattern?
: 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 por 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, lo 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 mapStateToProps
o algún análogo del mismo, estaría tentado a dividir su estado de otra manera para mejorar el rendimiento/simplificar.
Has entendido bien la primera parte:
Sí mapStateToProps
tiene el estado de la tienda como argumento/parámetro (proporcionado por react-redux::connect
) y se utiliza para vincular el componente con cierta parte del estado de la tienda.
Al vincular me refiero a que el 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 visualización 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 cambian el estado de la tienda (con la ayuda de filtersComponent
) reacciona -redux detecta que hubo un cambio y notifica o "publica" todos los componentes que escuchan/suscritos enviando los cambios a ellos, lo componentWillReceiveProps
que en este ejemplo activará un nuevo filtrado de los elementos y actualizará la pantalla debido al hecho de que el estado de reacción ha cambiado. .
Déjeme saber si el ejemplo es confuso o no es lo suficientemente claro como para brindar 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 está 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 utiliza para manejar el redibujado 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 de los cuales es responsable de administrar una pequeña porción de la lógica de la aplicación. ¡Se puede acceder a esos atributos de reductores con la ayuda de react-redux::connect@mapStateToProps
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 de sí mismo.