Comprensión de la gestión del estado de React y comparación de soluciones.

1. Reaccionar estado y comunicación
Por qué React necesita gestión estatal
Características de reacción:
  1. Centrarse en la capa de vista: las características de centrarse en la capa de vista determinan que no es un marco todo en uno. En comparación con marcos todo en uno como angular, React tiene funciones más simples y únicas.
  2. UI = render (datos) UI = render (datos), los datos son lo que llamamos flujo de datos y el render es una función pura proporcionada por reaccionar, por lo que la visualización de la interfaz de usuario depende completamente de la capa de datos.
  3. El estado fluye de arriba a abajo, los accesorios son de solo lectura. React representa la página según el estado (o accesorios). El estado fluye desde el exterior hacia el interior del componente, y de arriba a abajo, y los accesorios pasados ​​se leen. -solo.
Gestión de estado en componentes
Estado de reacción

Administre el estado a través del estado y actualice el estado usando setState para actualizar la interfaz de usuario

export default class Counter extends React.Component {
    
    
  constructor(props) {
    
    
    super(props);
    this.state = {
    
    
      value: 0,
      otherValue: 0
    };
  }

  handleAdd() {
    
    
    this.setState((state, props) => ({
    
    
    ...state,
      value: ++state.value
    }));
  }

  render() {
    
    
    return (
      <div>
        <p>{
    
    this.state.value}</p>
        <button onClick={
    
    () => this.handleAdd}>Add</button>
      </div>
    );
  }
}

Desventajas de la propia solución de gestión de estado de React: incluso si solo actualiza un determinado valor en el estado, debe traer otros valores (otherValue), lo cual es engorroso de operar.

Ganchos de reacción

Los ganchos se agregaron oficialmente en React 16.8. Administre el estado dentro de los componentes a través de ganchos, que es fácil de usar y escalable.

motivación:

  • Reutilizar la lógica de estado entre componentes es difícil
  • Los componentes complejos se vuelven difíciles de entender
  • clase incomprensible
  • El propósito de diseño de React Hooks es mejorar el componente funcional. Puede escribir un componente completamente funcional sin usar "clase" para definir el componente.
import React, {
    
     useState } from "react";

function Counter() {
    
    
  const [count, setCount] = useState(0);
  return (
    <div>
      <h1>{
    
    count}</h1>
      <button onClick={
    
    () => setCount(count + 1)}>Add</button>
    </div>
  );
}

export default Counter;

En comparación con el componente Clase, que utiliza el propio método de gestión de estado de React, React Hooks utiliza el método useState para crear variables de estado, actualizar métodos de estado y asignar estados iniciales en el componente Función. Esto implementa un componente Función con su propio estado.

Reaccionar comunicación de componentes

Hay tres soluciones de gestión del flujo de datos para reaccionar en sí:

  • Comunicación del componente padre-hijo
  • Comunicación del componente hermano
  • Comunicación entre componentes
Componentes padre-hijo

Pasar de padre a hijo: agregue datos de atributos al componente secundario a través de accesorios, para que el componente principal pueda comunicarse con el componente secundario.

Insertar descripción de la imagen aquí

Pasos de implementación

  1. El componente principal proporciona los datos que se pasarán:state

  2. Proporcione el 添加属性valor de la etiqueta del subcomponente como los datos en el estado

  3. El componente secundario propsrecibe los datos pasados ​​desde el componente principal a través de

    1. Los componentes de la clase usan this.props para obtener el objeto props.
    2. Los componentes funcionales obtienen objetos de accesorios directamente a través de parámetros.
import React from 'react'

// 函数式子组件
function FSon(props) {
    
    
  console.log(props)
  return (
    <div>
      子组件1
      {
    
    props.msg}
    </div>
  )
}

// 类子组件
class CSon extends React.Component {
    
    
  render() {
    
    
    return (
      <div>
        子组件2
        {
    
    this.props.msg}
      </div>
    )
  }
}
// 父组件
class App extends React.Component {
    
    
  state = {
    
    
    message: 'this is message'
  }
  render() {
    
    
    return (
      <div>
        <div>父组件</div>
        <FSon msg={
    
    this.state.message} />
        <CSon msg={
    
    this.state.message} />
      </div>
    )
  }
}

export default App

descripción de accesorios:

  1. props es un objeto de solo lectura (solo lectura) De acuerdo con los requisitos del flujo de datos único, los subcomponentes solo pueden leer los datos en props y no pueden modificarlos.
  2. Los accesorios pueden pasar cualquier número de datos, cadenas, valores booleanos, matrices, objetos, funciones, JSX.

Pasar de hijo a padre: el componente principal pasa la función de devolución de llamada al componente secundario y el componente secundario llama

Pasos de implementación

  1. El componente principal proporciona una función de devolución de llamada, que se utiliza para recibir datos.
  2. Pasar la función como valor del atributo al componente secundario
  3. Los componentes secundarios llaman a funciones de devolución de llamada a través de accesorios
  4. Pasar los datos del componente secundario como parámetro a la función de devolución de llamada

Insertar descripción de la imagen aquí

import React from 'react'

// 子组件
function Son(props) {
    
    
  function handleClick() {
    
    
    // 调用父组件传递过来的回调函数 并注入参数
    props.changeMsg('this is newMessage')
  }
  return (
    <div>
      {
    
    props.msg}
      <button onClick={
    
    handleClick}>change</button>
    </div>
  )
}


class App extends React.Component {
    
    
  state = {
    
    
    message: 'this is message'
  }
  // 提供回调函数
  changeMessage = (newMsg) => {
    
    
    console.log('子组件传过来的数据:',newMsg)
    this.setState({
    
    
      message: newMsg
    })
  }
  render() {
    
    
    return (
      <div>
        <div>父组件</div>
        <Son
          msg={
    
    this.state.message}
          // 传递给子组件
          changeMsg={
    
    this.changeMessage}
        />
      </div>
    )
  }
}

export default App
Comunicación del componente hermano

Componente hermano: a través del mecanismo de promoción estatal, el componente principal común se utiliza para lograr la comunicación entre hermanos.

Insertar descripción de la imagen aquí

mejora de estado

Promoción del estado: es decir, el estado que necesita ser comunicado se promueve al componente padre común de ambos para lograr compartir y reaccionar.

Insertar descripción de la imagen aquí

Contenido de implementación: A1 y B1 bajo los componentes A y B deben implementar la comunicación de estado

Insertar descripción de la imagen aquí

Proceso de mejora del estado: agregue un componente de Contenedor encima de A y B, y mejore el estado que A1 y B1 necesitan compartir, defínalo en el Contenedor y pase los métodos state y changeState a través de accesorios.

Un problema con este método es que si hay un estado del componente C en el futuro que necesita comunicarse con A, se agregará otro componente Contenedor. Si el estado de A necesita compartirse con C, será aún más devastador. Anteriormente, se actualizó a El estado del contenedor debe mejorarse a otro nivel. Para este interminable problema de promoción estatal, el costo de comunicación en la etapa posterior es muy alto, casi reescritura.

Pasos de implementación

  1. Promocionar el estado compartido al componente principal público más cercano, que administra este estado
    • Proporcionar estado compartido
    • Proporciona métodos para manipular el estado compartido.
  1. Los subcomponentes que desean recibir el estado de los datos reciben datos a través de accesorios
  2. Los subcomponentes que desean transferir el estado de los datos reciben métodos a través de accesorios y llaman a métodos para transferir datos.
import React from 'react'

// 子组件A
function SonA(props) {
    
    
  return (
    <div>
      SonA
      {
    
    props.msg}
    </div>
  )
}
// 子组件B
function SonB(props) {
    
    
  return (
    <div>
      SonB
      <button onClick={
    
    () => props.changeMsg('new message')}>changeMsg</button>
    </div>
  )
}

// 父组件
class App extends React.Component {
    
    
  // 父组件提供状态数据
  state = {
    
    
    message: 'this is message'
  }
  // 父组件提供修改数据的方法
  changeMsg = (newMsg) => {
    
    
    this.setState({
    
    
      message: newMsg
    })
  }

  render() {
    
    
    return (
      <>
        {
    
    /* 接收数据的组件 */}
        <SonA msg={
    
    this.state.message} />
        {
    
    /* 修改数据的组件 */}
        <SonB changeMsg={
    
    this.changeMsg} />
      </>
    )
  }
}

export default App
Contexto entre componentes:

Contexto entre componentes: el contexto proporciona un método para transferir datos entre árboles de componentes sin agregar accesorios manualmente a cada capa de componentes.

Pasos de implementación

1- Cree un objeto de contexto para exportar objetos de proveedor y consumidor

const {
    
     Provider, Consumer } = createContext()

2- Utilice el proveedor para envolver el componente superior y proporcionar datos

<Provider value={
    
    this.state.message}>
    {
    
    /* 根组件 */}
</Provider>

3- Los componentes que necesitan utilizar datos utilizan el paquete Consumer para obtener los datos.

<Consumer >
    {
    
    value => /* 基于 context 值进行渲染*/}
</Consumer>

código completo

import React, {
    
     createContext }  from 'react'

// 1. 创建Context对象 
const {
    
     Provider, Consumer } = createContext()


// 3. 消费数据
function ComC() {
    
    
  return (
    <Consumer >
      {
    
    value => <div>{
    
    value}</div>}
    </Consumer>
  )
}

function ComA() {
    
    
  return (
    <ComC/>
  )
}

// 2. 提供数据
class App extends React.Component {
    
    
  state = {
    
    
    message: 'this is message'
  }
  render() {
    
    
    return (
      <Provider value={
    
    this.state.message}>
        <div className="app">
          <ComA />
        </div>
      </Provider>
    )
  }
}

export default App

pregunta:

  • El contexto solo se implementa promoviendo el estado a un componente principal compartido. Parece ser entre componentes, pero de hecho todavía se pasa nivel por nivel para lograr la comunicación entre componentes, la sincronización de estados y el intercambio de estados.
  • El contexto también entrega el control de estado del subcomponente inferior al componente de nivel superior, pero cuando se actualiza el estado del componente de nivel superior, definitivamente activará la repetición de todos los subcomponentes, lo que también provocará pérdidas. .
Problemas causados ​​por la comunicación entre componentes:
  • Componentes inflados: cuando la lógica de negocios de un componente es muy compleja, encontraremos que cuanto más código escribimos, más código escribimos, porque solo podemos controlar el flujo de datos dentro del componente y no podemos separarlo.El modelo y la vista son ambos colocados en la capa Ver y todo el componente Parece inflado y difícil de mantener.
  • El estado es impredecible e incluso no se puede rastrear: cuando el flujo de datos es caótico, una acción de ejecución puede desencadenar una serie de setState y todo el flujo de datos se vuelve incontrolable.
  • Manejo del flujo de datos asincrónicos: React en sí no proporciona una variedad de soluciones para la gestión del flujo de datos asincrónicos. Es difícil cumplir con algunos escenarios complejos de flujo asincrónico con un solo setState.
  • El estado mejora constantemente y el contexto no es fácil de utilizar.
Definición de gestión estatal:

En pocas palabras, la "gestión estatal" consiste en resolver la comunicación "entre niveles" entre componentes.

  • Un componente necesita compartir estado con otro componente.
  • Un componente necesita cambiar el estado de otro componente.
2、Flujo —> Redux —> Mobx
El nacimiento del patrón arquitectónico Flux

Flux es un conjunto de patrones arquitectónicos, no un marco de código.

[Flujo de datos unidireccional]: Acción -> Dispatcher -> Tienda -> Ver flujo de datos interactivo de la página, por ejemplo, el usuario hace clic en el botón: Ver -> Crear acción -> Dispatcher (ingrese [Flujo de datos unidireccional] desde aquí )

Cuatro partes centrales

  • Despachador: Responsable de dos cosas, una es distribuir y procesar la Acción y la otra es mantener la Tienda.
  • Tienda: datos y parte lógica.
  • vistas: componente Page-React, obtiene el estado (datos) de la Tienda y vincula el procesamiento de eventos.
  • acciones: la interacción se encapsula como acción y se envía a la Tienda para su procesamiento.

(Error en la transferencia de la imagen del enlace externo. El sitio de origen puede tener un mecanismo anti-leeching. Se recomienda guardar la imagen y cargarla directamente (img-4Lni0WBa-1687931092907) (C:\Users\changwenqiao\AppData\Roaming\Typora\ typora-user-images\ image-20230610100446215.png)]

redux

Redux es una evolución de Flux: es un marco de código generado bajo la guía del patrón arquitectónico Flux y además lleva a cabo el diseño de restricciones arquitectónicas.

¿Por qué utilizar Redux?
  1. Independiente de los componentes, ignora las relaciones jerárquicas entre los componentes y simplifica los problemas de comunicación.
  2. El flujo de datos único es claro, lo que facilita la localización de errores.
  3. Las herramientas de depuración están bien equipadas y son convenientes para la depuración.
Tres principios:

1. Unicidad de la fuente de datos: todos los datos en redux se almacenan en un almacén, que es un árbol de estado único e inmutable, cuyo propósito es garantizar la unicidad de la fuente de datos. Un árbol de estado único también facilita la depuración o inspección de la aplicación.

2. El estado solo puede ser de solo lectura: el estado solo puede ser de solo lectura. El estado solo se puede cambiar activando una acción. Puede obtener el valor en la acción, pero no puede cambiarlo. El método adoptado en este momento es Por lo general, copia en profundidad el estado, lo devuelve a una variable, luego cambia la variable y finalmente devuelve el valor. Y los datos solo se pueden cambiar en el reductor. El reductor es un proceso de función que describe qué tipo de proceso ocurre en el objeto. El beneficio del estado de solo lectura es que garantiza que ni las vistas ni las devoluciones de llamada de la red escriban directamente en el estado.

3. Utilice funciones puras para realizar cambios: la esencia del reductor es en realidad una función pura. Cada cambio siempre devuelve un nuevo estado.

Arquitectura de flujo de datos de Redux

Insertar descripción de la imagen aquí

  • Tienda: proporciona una variable de tienda global para almacenar los estados públicos que queremos extraer del componente;
  • acción: proporciona un objeto común para describir cómo desea cambiar los datos, y esta es la única manera;
  • reductor: proporciona una función pura para actualizar el estado de acuerdo con la descripción de la acción
Implementación Pure Redux de contador

pasos centrales

  1. Cree una función reductora y defina la relación entre acción y estado internamente.
  2. Llame al método createStore de Redux y pase la función reductora definida para generar una instancia de tienda.
  3. Supervisar si los datos cambian a través del método de suscripción en la instancia de la tienda
  4. Haga clic en el botón para enviar el objeto de acción a través de la función de envío especial para implementar la actualización de datos.
<button id="decrement">-</button>
<span id="count">0</span>
<button id="increment">+</button>

<script src="https://unpkg.com/redux@latest/dist/redux.min.js"></script>

<script>
  // 定义reducer函数 
  // 内部主要的工作是根据不同的action 返回不同的state
  function counterReducer (state = {
     
      count: 0 }, action) {
    
    
    switch (action.type) {
    
    
      case 'INCREMENT':
        return {
    
     count: state.count + 1 }
      case 'DECREMENT':
        return {
    
     count: state.count - 1 }
      default:
        return state
    }
  }
  // 使用reducer函数生成store实例
  const store = Redux.createStore(counterReducer)
  
  // 订阅数据变化
  store.subscribe(() => {
    
    
    console.log(store.getState())
    document.getElementById('count').innerText = store.getState().count
    
  })
  // 增
  const inBtn = document.getElementById('increment')
  inBtn.addEventListener('click', () => {
    
    
    store.dispatch({
    
    
      type: 'INCREMENT'
    })
  })
  // 减
  const dBtn = document.getElementById('decrement')
  dBtn.addEventListener('click', () => {
    
    
    store.dispatch({
    
    
      type: 'DECREMENT'
    })
  })
</script>
Procesamiento asincrónico de Redux
import {
    
     createSlice } from '@reduxjs/toolkit'
import axios from 'axios'

const channelStore = createSlice({
    
    
  name: 'channel',
  initialState: {
    
    
    channelList: []
  },
  reducers: {
    
    
    setChannelList (state, action) {
    
    
      state.channelList = action.payload
    }
  }
})


// 创建异步
const {
    
     setChannelList } = channelStore.actions
const url = 'http://geek.itheima.net/v1_0/channels'
// 封装一个函数 在函数中return一个新函数 在新函数中封装异步
// 得到数据之后通过dispatch函数 触发修改
const fetchChannelList = () => {
    
    
  return async (dispatch) => {
    
    
    const res = await axios.get(url)
    dispatch(setChannelList(res.data.data.channels))
  }
}

export {
    
     fetchChannelList }

const channelReducer = channelStore.reducer
export default channelReducer
import {
    
     useEffect } from 'react'
import {
    
     useSelector, useDispatch } from 'react-redux'
import {
    
     fetchChannelList } from './store/channelStore'

function App () {
    
    
  // 使用数据
  const {
    
     channelList } = useSelector(state => state.channel)
  useEffect(() => {
    
    
    dispatch(fetchChannelList())
  }, [dispatch])

  return (
    <div className="App">
      <ul>
        {
    
    channelList.map(task => <li key={
    
    task.id}>{
    
    task.name}</li>)}
      </ul>
    </div>
  )
}

export default App
¿Cuándo deberías usar Redux?

Cuando es necesario procesar estados de aplicaciones complejos y React por sí solo no puede satisfacerlos . Por ejemplo:

  • Es necesario conservar el estado de la aplicación para que pueda restaurarse desde el almacenamiento local o desde los datos devueltos por el servidor.
  • Necesidad de implementar funciones de deshacer y rehacer
  • Habilitar la colaboración de usuarios entre páginas
  • Cuando el estado de la aplicación es complejo
  • Cuando el flujo de datos es más complejo
  • Muchos componentes no relacionados necesitan compartir y actualizar el estado
  • estado externo
Desventajas de redux:
  • Plantillas de código pesado: modificar un estado puede requerir mover cuatro o cinco archivos;
  • Resto de estado en la tienda: cuando varios componentes comparten un determinado estado en la tienda, se debe prestar atención a los problemas de inicialización y eliminación;
  • Publicar y suscribirse sin sentido: cada vez que se envía una acción, se atravesarán todos los reductores y se recalcularán las conexiones, lo que sin duda es una pérdida;
  • Habrá retrasos cuando las interacciones sean frecuentes: si la tienda es grande y se modifica con frecuencia, obviamente verá retrasos en la página;
  • El texto mecanografiado no es compatible;
mobx

Una herramienta de gestión de estado centralizada que puede funcionar bien con React, resuelve problemas similares a Redux y puede realizar una gestión de estado centralizada en componentes independientes.

Mobx proporciona un sistema receptivo similar a Vue y, en comparación con Redux, la arquitectura de Mobx es más fácil de entender.

flujo de datos mobx

Insertar descripción de la imagen aquí

Datos reactivos : primer uso @observablepara convertir los datos en 'datos reactivos', similar a los datos de Vue. Las dependencias se pueden recopilar cuando se accede a estos datos en algún contexto (como el cálculo, el componente React envuelto del observador, la reacción), y las dependencias relacionadas se notificarán cuando estos datos cambien. Dos ventajas que aportan los datos reactivos son ① Métodos de operación de datos simplificados (en comparación a redux y setState); ② Enlace de datos preciso, la vista solo necesita representarse cuando los datos realmente cambian. Cuanto menor sea la granularidad de las dependencias de los componentes, más finamente se actualizará la vista.

centro:

Las acciones cambian de estado y los cambios de estado actualizan todas las vistas afectadas

Uso básico

Inicializar mobx

Pasos de inicialización

  1. Definir estado de estado de datos
  2. Implementar procesamiento de respuesta de datos en el constructor makeAutoObservble
  3. Definir acción de función para modificar datos.
  4. Crear una instancia de la tienda y exportarla.
import {
    
     makeAutoObservable } from 'mobx'

class CounterStore {
    
    
  count = 0 // 定义数据
  constructor() {
    
    
    makeAutoObservable(this)  // 响应式处理
  }
  // 定义修改数据的方法
  addCount = () => {
    
    
    this.count++
  }
}

const counter = new CounterStore()
export default counter

Reaccionar usa la tienda

Pasos de implementación

  1. Importar el objeto de instancia de counterStore en el componente
  2. Utilice los datos del objeto de instancia storeStore en el componente
  3. Modifique los datos en la tienda llamando a métodos que modifican los datos a través de eventos.
  4. Permitir que los componentes respondan a los cambios de datos
// 导入counterStore
import counterStore from './store'
// 导入observer方法
import {
    
     observer } from 'mobx-react-lite'
function App() {
    
    
  return (
    <div className="App">
      <button onClick={
    
    () => counterStore.addCount()}>
        {
    
    counterStore.count}
      </button>
    </div>
  )
}
// 包裹组件让视图响应数据变化
export default observer(App)

Propiedades calculadas (estado derivado)

Algunos estados se calculan (derivan) de los estados existentes.

Insertar descripción de la imagen aquí

Pasos de implementación

  1. La vida es un dato existente.
  2. Definir propiedades calculadas mediante la palabra clave get
  3. Marcar propiedades calculadas en el método makeAutoObservable
import {
    
     computed, makeAutoObservable } from 'mobx'

class CounterStore {
    
    
  list = [1, 2, 3, 4, 5, 6]
  constructor() {
    
    
    makeAutoObservable(this, {
    
    
      filterList: computed
    })
  }
  // 修改原数组
  changeList = () => {
    
    
    this.list.push(7, 8, 9)
  }
  // 定义计算属性
  get filterList () {
    
    
    return this.list.filter(item => item > 4)
  }
}

const counter = new CounterStore()

export default counter
// 导入counterStore
import counterStore from './store'
// 导入observer方法
import {
    
     observer } from 'mobx-react-lite'
function App() {
    
    
  return (
    <div className="App">
      {
    
    /* 原数组 */}
      {
    
    JSON.stringify(counterStore.list)}
      {
    
    /* 计算属性 */}
      {
    
    JSON.stringify(counterStore.filterList)}
      <button onClick={
    
    () => counterStore.changeList()}>change list</button>
    </div>
  )
}
// 包裹组件让视图响应数据变化
export default observer(App)

Procesamiento de datos asíncrono

Pasos de implementación:

  1. Escriba un método de solicitud asincrónica en mobx para obtener datos y almacenarlos en estado
  2. La ejecución de la función de acción se activa en el componente mediante useEffect + dependencia vacía
// 异步的获取

import {
    
     makeAutoObservable } from 'mobx'
import axios from 'axios'

class ChannelStore {
    
    
  channelList = []
  constructor() {
    
    
    makeAutoObservable(this)
  }
  // 只要调用这个方法 就可以从后端拿到数据并且存入channelList
  setChannelList = async () => {
    
    
    const res = await axios.get('http://geek.itheima.net/v1_0/channels')
    this.channelList = res.data.data.channels
  }
}
const channlStore = new ChannelStore()
export default channlStore
import {
    
     useEffect } from 'react'
import {
    
     useStore } from './store'
import {
    
     observer } from 'mobx-react-lite'
function App() {
    
    
  const {
    
     channlStore } = useStore()
  // 1. 使用数据渲染组件
  // 2. 触发action函数发送异步请求
  useEffect(() => {
    
    
    channlStore.setChannelList()
  }, [])
  return (
    <ul>
      {
    
    channlStore.channelList.map((item) => (
        <li key={
    
    item.id}>{
    
    item.name}</li>
      ))}
    </ul>
  )
}
// 让组件可以响应数据的变化[也就是数据一变组件重新渲染]
export default observer(App)

Modular

Insertar descripción de la imagen aquí

Pasos de implementación

  1. Divida el archivo js del módulo y defina su propio estado/acción independiente en cada módulo
  2. Importe los módulos divididos en store/index.js y combine los módulos
  3. Utilice el mecanismo de contexto de React para exportar un método useStore unificado para que lo utilicen los componentes comerciales

1- Definir módulo de tareas

import {
    
     makeAutoObservable } from 'mobx'

class TaskStore {
    
    
  taskList = []
  constructor() {
    
    
    makeAutoObservable(this)
  }
  addTask () {
    
    
    this.taskList.push('vue', 'react')
  }
}

const task = new TaskStore()


export default task

2- Definir mostradorTienda

import {
    
     makeAutoObservable } from 'mobx'

class CounterStore {
    
    
  count = 0
  list = [1, 2, 3, 4, 5, 6]
  constructor() {
    
    
    makeAutoObservable(this)
  }
  addCount = () => {
    
    
    this.count++
  }
  changeList = () => {
    
    
    this.list.push(7, 8, 9)
  }
  get filterList () {
    
    
    return this.list.filter(item => item > 4)
  }
}

const counter = new CounterStore()

export default counter

3- Los módulos combinados exportan métodos unificados.

import React from 'react'

import counter from './counterStore'
import task from './taskStore'


class RootStore {
    
    
  constructor() {
    
    
    this.counterStore = counter
    this.taskStore = task
  }
}


const rootStore = new RootStore()

// context机制的数据查找链  Provider如果找不到 就找createContext方法执行时传入的参数
const context = React.createContext(rootStore)

const useStore = () => React.useContext(context)
// useStore() =>  rootStore  { counterStore, taskStore }

export {
    
     useStore }

4- El componente utiliza datos del módulo.

import {
    
     observer } from 'mobx-react-lite'
// 导入方法
import {
    
     useStore } from './store'
function App() {
    
    
  // 得到store
  const store = useStore()
  return (
    <div className="App">
      <button onClick={
    
    () => store.counterStore.addCount()}>
        {
    
    store.counterStore.count}
      </button>
    </div>
  )
}
// 包裹组件让视图响应数据变化
export default observer(App)
Defectos de mobx
  • Sin capacidad de retroceso de estado: mobx modifica directamente la referencia del objeto, por lo que es difícil realizar un retroceso de estado; (la ventaja de redux se refleja instantáneamente)
  • Sin middleware: al igual que redux, mobx no tiene una buena forma de manejar el flujo de datos asincrónicos y no hay forma de controlar el flujo de datos con mayor precisión.
  • Demasiadas tiendas: a medida que aumenta el número de tiendas, los costos de mantenimiento también aumentarán y el intercambio de datos y las referencias mutuas entre varias tiendas también serán propensos a errores.
  • Efectos secundarios: mobx modifica directamente los datos, lo que es contrario a las funciones puras enfatizadas por el modelo de programación funcional, lo que también genera muchas incógnitas en los datos.
Comparación entre Mobx y Redux

redux

  • Redux almacena datos en una sola tienda
  • Redux utiliza objetos simples para guardar datos y usted debe manejar manualmente las operaciones modificadas.
  • Redux usa un estado inmutable, lo que significa que el estado es solo de lectura y no se puede modificar directamente, sino que se debe devolver un nuevo estado y se deben usar funciones puras.
  • Redux será más complicado porque las ideas de programación funcional no son tan fáciles de dominar y se necesita una serie de middleware para manejar los efectos asincrónicos y secundarios.
  • Flujo de datos: envío (acción) -> llamar al reductor en la tienda, comparar el estado actual con la acción recibida, calcular el nuevo estado -> el estado cambia, la tienda monitorea el cambio -> comenzar a volver a renderizar

mobx

  • mobx almacena datos en múltiples almacenes independientes, divididos por aplicación de módulo
  • mobx utiliza observable para guardar datos y maneja automáticamente las operaciones de respuesta después de cambios de datos.
  • El estado en mobx es mutable y se puede modificar directamente
  • Mobx es relativamente simple y tiene muchas abstracciones. Mobx utiliza un pensamiento más orientado a objetos.
  • Flujo de datos: acción -> modificar estado -> desencadenar cambios

Resumir

  • Si es un proyecto pequeño y no hay mucho estado que compartir, entonces no hay necesidad de gestión estatal. Los accesorios o el contexto de reacción en sí pueden cumplir con los requisitos.
  • Si necesita controlar manualmente las actualizaciones de estado, el flujo de datos unidireccional es una opción adecuada, por ejemplo: redux
  • Si necesita actualizaciones automáticas simples, la gestión de estado vinculante bidireccional es la mejor opción, por ejemplo: mobx
  • En proyectos pequeños o con un número reducido de desarrolladores, se puede utilizar MobX, que será más eficiente.
  • Para proyectos grandes o proyectos con ayuda de varias personas, considere usar Redux, lo que reducirá los costos de mantenimiento posteriores.
  • Si se trata de un simple intercambio de datos entre dos o más componentes, entonces la atomización puede ser una opción adecuada: por ejemplo: jotai, retroceso
  • Si el estado tiene un procesamiento de flujo de datos complejo, utilice rxjs
  • Si administra estados comerciales complejos, puede usar una máquina de estados finitos para administrar transiciones de estado, por ejemplo: xstate
  • Si es necesario suscribirse y operar el estado en un contexto sin reacción, herramientas como jotai y recoil no son buenas opciones.

Supongo que te gusta

Origin blog.csdn.net/qq_43641110/article/details/131435161
Recomendado
Clasificación