ReactJS: ¿Por qué pasar el estado inicial del componente a prop es un anti-patrón?

79

Creé un pequeño panel de ReactJS con la ayuda de SocketIO para actualizaciones en vivo. Aunque tengo la actualización del tablero, me molesta que no esté muy seguro de si lo hice correctamente.

Lo que más me molesta son los Props en getInitialState como publicación anti-patrón . Creé un panel que recibe actualizaciones en vivo desde un servidor, sin necesidad de interacción del usuario más allá de cargar la página. Por lo que he leído, this.statedebería contener cosas que determinarán si el componente debería volver a renderizarse y this.props... todavía no lo sé.

Sin embargo, cuando llama inicialmente React.render(<MyComponent />, ...), solo puede pasar apoyos. En mi caso, obtengo todos los datos del servidor, por lo que los accesorios iniciales simplemente terminan de this.statetodos modos. Entonces todos mis componentes tienen algo como esto:

getInitialState: function() {
    return {
        progress: this.props.progress,
        latest_update: this.props.latest_update,
        nearest_center: this.props.nearest_center
    }
}

Lo cual, a menos que haya malinterpretado la publicación de blog antes mencionada, es un anti-patrón. Pero no veo otra forma de inyectar el estado en el Componente, y no entiendo por qué es un anti-patrón a menos que vuelva a etiquetar todos mis accesorios para anteponerlos initial. En todo caso, siento que eso es un anti-patrón porque ahora tengo que hacer un seguimiento de más variables que antes (las que están precedidas por initialy las que no).

charmeleon
fuente
1
En 2017, Facebook demuestra el uso de accesorios para establecer el estado inicial en su documentación: reactjs.org/docs/react-component.html#constructor
Rohmer
1
El enlace de @ Rohmer contiene un enlace a Probablemente no necesite un estado derivado , que tiene una discusión en profundidad de las alternativas y qué evitar.
ToolmakerSteve

Respuestas:

94

Descargo de responsabilidad : cuando respondí esta pregunta, estaba aprendiendo / tratando de implementar Vanilla Flux y estaba un poco escéptico al respecto. Más tarde, migré todo a Redux. Entonces, un consejo: simplemente elija Redux o MobX. Lo más probable es que ya no necesite la respuesta a esta pregunta (a excepción de la ciencia).

Pasar el estado inicial a un componente como a propes un anti-patrón porque el getInitialStatemétodo solo se llama la primera vez que se procesa el componente. Lo que significa que, si vuelve a renderizar ese componente pasando un valor diferente como a prop, el componente no reaccionará en consecuencia, porque el componente mantendrá el estado de la primera vez que se renderizó. Es muy propenso a errores.

Y esto es lo que debe hacer:

Intente hacer que sus componentes sean lo más apátridas posible. Los componentes sin estado son más fáciles de probar porque generan una salida basada en una entrada . Tan simple como eso.

Pero bueno ... los datos de mis componentes cambian ... no puedo convertirlos en apátridas

Sí, puede, para la mayoría de ellos. Para hacer eso, seleccione un componente externo para que sea el titular del estado. Usando su ejemplo, podría crear un Dashboardcomponente que contenga los datos y un Widgetcomponente que sea completamente sin estado. El Dashboardes responsable de obtener todos los datos y luego renderizar múltiples Widgetsque reciben todo lo que necesitan props.

Pero mis widgets tienen algún estado ... el usuario puede configurarlos. ¿Cómo puedo convertirlos en apátridas?

Su Widgetpuede exponer a eventos que, cuando se maneja, hacen que el estado contenida en Dashboardel cambio, haciendo que todos los Widgetque se rerendered. Creas "eventos" en tu Widgetal hacer propsque reciban una función.

Bien, ahora Dashboard mantiene el estado, pero ¿cómo le paso el estado inicial?

Tienes dos opciones. La más recomendada es que hagas una llamada Ajax en el Dashboard getInitialStatemétodo para obtener el estado inicial del servidor. También puede usar Flux , que es una forma más sofisticada de administrar datos. Flux es más un patrón que una implementación. Puede usar Flux puro con la implementación de Facebook del Dispatcher, pero puede usar implementaciones de terceros como Redux , Alt o Fluxxor .

Alternativamente, puede pasar este estado inicial como propa al Dashboard, declarando explícitamente que este es solo el estado inicial ... como initialData, por ejemplo. Sin embargo, si elige esta ruta, no puede pasarle un estado inicial diferente hacia adelante, porque "recordará" el estado después del primer renderizado.

OBS

No tiene mucha razón en sus definiciones.

El estado se usa para almacenar datos mutables, es decir, datos que van a cambiar durante el ciclo de vida del componente. Los cambios en el estado deben realizarse a través del setStatemétodo y harán que el componente vuelva a renderizarse.

Los accesorios se utilizan para pasar datos imutables a los componentes. No deben cambiar durante el ciclo de vida del componente. Los componentes que solo usan accesorios no tienen estado.

Esta es una fuente relevante sobre "cómo pasar el estado inicial a los componentes".

André Pena
fuente
se describe muy bien, pero ... como siempre es un 'pero'. ¿Qué pasa si tengo un componente, que obtiene una matriz de imágenes y crea componentes secundarios con miniaturas y un evento onlick, que debería cambiar la imagen grande en este componente? Las imágenes no están en estado, por lo que no puedo usar otro componente para mantenerlas. Las imágenes son locales y necesito un estado local para administrar, lo que debería mostrarse como una imagen grande. Me encantaría usar accesorios en el estado, pero recibo Advertencia: setState (...): No se puede actualizar durante una transición de estado existente (como dentro render). Los métodos de renderización deben ser una función pura de accesorios y estado.
Kania
10
Entonces, ¿alguna opinión sobre el uso componentWillReceiveProps(nextProps)para establecer el estado?
Alejandro
1
componentWillRecieveProps () está obsoleto a partir de 16.3 así que ... No. No lo use.
Rap
@Alejandro - estado Es probable que no dimanante es una explicación a fondo de los riesgos en el uso (en desuso) componentWillReceiveProps, o su reemplazo (no se use), getDerivedStateFromProps. En pocas palabras: el artículo muestra varias soluciones alternativas, que no llaman a ninguno de esos métodos, y explica por qué utilizar estas alternativas en su lugar.
ToolmakerSteve