「✍ Mobx」搭配 React + Typescript食用

前言

之前项目中状态管理清一色的都是用redux,各种redux实践也尝试过,但是给人感觉还是特别的重(redux-toolkit还不错),因此入坑尝试口碑不错的mobx

Begin

创建一个Store

这里我们以一个todolist为例子

import { observable, action, makeObservable } from 'mobx';

class Todo {
  constructor() {
    // mobx6.0后的版本都需要手动调用makeObservable(this),不然会发现数据变了视图不更新
    makeObservable(this); 
  }
  @observable list = [
    {
      label: 'exec',
      finish: false,
    },
    {
      label: 'study',
      finish: false,
    },
  ];

  @action
  finsh(label: string) {
    let list = [...this.list];
    list.map(item => {
      if (item.label === label) {
        item.finish = true;
      }
      return item;
    });
    this.list = list;
  }
}
const todoStore = new Todo();
export default todoStore;
复制代码

@observable

创建一个可响应的变量,注意这里并不是原始变量

@action

这其实就是redux中的action,据说老版本中mobx是直接修改state的,听起来就非常不安全。这种使用action触发动作的形式似乎更能让人接受

编写业务组件

获取响应式数据,我们一般有两种形式,一种是直接引入定义的Store, 一种是利用Provider和inject来注入到组件的props中

直接引入store

import React from 'react';
import { observer } from 'mobx-react';
import todoStore from '../../store/todo'

@observer
class Todo extends React.Component{
  render() {
    return (
      <div className="todolist">
        <div className="unfinish">
          {todoStore.list.map(item => (
            <div key={item.label} style={{ display: 'flex' }}>
              {!item.finish && (
                <>
                  <span>{item.label}</span>
                  <button onClick={() => todoStore.finsh(item.label)}>do</button>
                </>
              )}
            </div>
          ))}
        </div>

        <div className="finish">
          {todoStore.list.map(item => (
            <div key={item.label}>{item.finish && <span>{item.label}</span>}</div>
          ))}
        </div>
      </div>
    );
  }
}

export default Todo;
复制代码

父组件

<div>
  <Todo />
</div>
复制代码

使用Provider和inject

import React from 'react';
import { observer, inject } from 'mobx-react';

@inject('todoStore')
@observer
class Todo extends React.Component{
  render() {
    const { todoStore } = this.props
    return (
      <div className="todolist">
        <div className="unfinish">
          {todoStore.list.map(item => (
            <div key={item.label} style={{ display: 'flex' }}>
              {!item.finish && (
                <>
                  <span>{item.label}</span>
                  <button onClick={() => todoStore.finsh(item.label)}>do</button>
                </>
              )}
            </div>
          ))}
        </div>

        <div className="finish">
          {todoStore.list.map(item => (
            <div key={item.label}>{item.finish && <span>{item.label}</span>}</div>
          ))}
        </div>
      </div>
    );
  }
}

export default Todo;

复制代码

父组件

import todoStore from '../store/todo';
<Provider todoStore={todoStore} >
    <Todo />
</Provider>
复制代码

inject的方式有个缺点,typescript支持不太好,注入之后还得手动写props的类型,体验一般

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享