Estoy hablando del argumento mapStateToProps de connect .
Uno de mis componentes tiene una propiedad llamada rules que es una matriz de funciones. En mapStateToProps invoco esas reglas, pasando el estado actual. Las reglas devuelven un mensaje de error o son true si no hay ningún error. Coloco estos mensajes de error en un nuevo accesorio para que el componente final reciba una serie de mensajes de error en lugar de una serie de funciones.
Hasta ahora, esto ha funcionado muy bien, pero ahora quiero agregar soporte para reglas asincrónicas. Mi plan en este momento es que cada vez que una regla devuelva una Promesa en lugar de una cadena de error, enviaré un mensaje como "Comprobando..." en la matriz de mensajes de error, pero una vez que se resuelva la promesa, necesito "actualizar" esta matriz e inserte el mensaje resuelto.
Me imagino que si puedo forzar una actualización , redux tendrá que volver a llamar a mapStateToProps . En tal caso, todas las reglas serían reevaluadas, pero si no tengo cuidado, recibiría una nueva Promesa que volvería al punto de partida. Sin embargo, si memorizo estas reglas, entonces puedo recuperar la misma instancia de Promise que antes, y luego verificar si está resuelto y luego poner ese valor en mi matriz de errores.
Entonces, ahora el único problema es descubrir cómo obtener una referencia a la instancia del componente dentro del contexto de mapStateToProps que solo tiene acceso al estado actual y las propiedades.
¿Hay alguna manera de forzar una nueva representación una vez que mi Promesa se haya resuelto?
Alternativamente, si pudiera dispatch una acción cuando se resuelva, también podría trabajar con eso.
No puedes hacer eso en mapState . La función mapState está pensada para ser totalmente síncrona. Si necesita hacer algo asíncrono, actívelo fuera de mapState , almacene algunos valores en el estado y actualícelos con los resultados para obligar a mapState a volver a ejecutarse.
¿Qué tal crear un componente con estado? Si mantiene los resultados de sus promesas en el estado del componente, volverá a procesar automáticamente el componente una vez que se resuelvan las promesas.
import React, {Component} from 'react'; import {connect} from 'react-redux; import Promise from 'promise'; class MyStatefulComponent extends Component { constructor(props) { this.state = { messages: [] // initialize empty, or with the synchronous rules }; } componentWillMount() { const setState = this.setState; const rules = this.props.rules; // rules contains a list of either evaluated rules or promises Promise.all(rules).then(results => { // this is executed once all the promises in rules have resolved // setState will trigger a re-render of this component setState({ messages: [] // construct your array of messages here from the results }); }) } render() { // render your list of messages return <ul> {this.state.messages.map(message => <li>{message}</li>)} </ul>; } } export default connect( (state, ownProps) => ({ rules: ownProps.rules.map(rule => rule(state)) }) )(MyStatefulComponent);