Comprender React-Redux y mapStateToProps()

Resuelto Pablo Barría Urenda asked hace 8 años • 10 respuestas

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 mapStateToPropsserá 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?

Pablo Barría Urenda avatar Jul 05 '16 18:07 Pablo Barría Urenda
Aceptado

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 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.postscomponente 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 bindActionCreatorsusted 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, bindActionCreatorssimplemente tomaremos sus acciones y las envolveremos en dispatchuna 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;
  }, {})
}
webdeb avatar Jul 05 '2016 13:07 webdeb

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 mapStateToPropso algún análogo del mismo, estaría tentado a dividir su estado de otra manera para mejorar el rendimiento/simplificar.

Richard Strickland avatar Sep 26 '2017 14:09 Richard Strickland

Has entendido bien la primera parte:

mapStateToPropstiene 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 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 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 itemsFiltersque 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 componentWillReceivePropsque 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@mapStateToPropscualquier 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.

Mohamed Mellouki avatar Jul 05 '2016 12:07 Mohamed Mellouki