什么?在React中也可以使用vue响应式状态管理

183 阅读2分钟

随着Vue流行起来,使用响应式状态管理的方式愈发的流行,那么我们今天来试试在react中使用响应式状态管理方式

@lujs/use-reactive-state

@lujs/use-reactive-state是一个在react使用的响应式状态管理库,支持hooks

  • 简单
  • 帮助你划分ui和业务状态
  • 完善的Typescript支持

这个是笔者两年前发布的一个react状态库,已经使用两年多了,欢迎使用

使用

首先安装@lujs/use-reactive-state

npm i @lujs/use-reactive-state

createReactiveState

使用createReactiveState方法来创建一个响应式对象

const vm = createReactiveState(object);

useReactiveState

使用useReactiveState在react中绑定响应式对象,就可以做到响应式更新了,具体看下方例子

import React from 'react';
import {
  createReactiveState,
  useReactiveState,
} from '@lujs/use-reactive-state';


class Vm {
  name = 'use-react-state';

  setName(name: string) {
    this.name = name;
  }
}

const vm = createReactiveState(new Vm());

const ComA = () => {
  useReactiveState(vm);
  return (
    <div>
      <p>name1:{vm.name}</p>
    </div>
  );
};

selector

支持选择器,比如下方的里只有在s.obj.age更新的时候才会触发组件渲染

const state = createReactiveState({
  name: 'lujs',
  obj: {
    age: 18,
  },
});

// ComA will render when state.obj.age change
const ComA = () => {
  useReactiveState(state, s => s.obj.age);
  return (
    <div>
      <p>name1:{state.obj.age}</p>
    </div>
  );
};

debug

在浏览器中使用react dev tool可以看到debug的状态
debug

TodoList

下面演示一个简单的Todolist

import {
  createReactiveState,
  useReactiveState,
} from '@lujs/use-reactive-state';
import React, { useRef, useEffect } from 'react';

class Todo {
  content = '';

  id = '';

  status: 'done' | 'default' | 'delete' = 'default';

  constructor(content: string) {
    this.content = content;
    this.id = Math.random().toString();
  }

  finish() {
    if (this.status === 'default') {
      this.status = 'done';
    } else if (this.status === 'done') {
      this.status = 'delete';
    }
  }

  setContent(s: string) {
    this.content = s;
  }
}

class TodoList {
  list: Todo[] = [];

  addTodo(content: string) {
    const todo = new Todo(content);
    this.list.push(todo);
  }

  init() {
    this.addTodo('todo 1');
  }

  finish(id: string) {
    this.list.forEach(v => {
      if (v.id === id) {
        v.finish();
      }
    });
  }

  defaultList() {
    return this.list.filter(v => v.status === 'default');
  }

  doneList() {
    return this.list.filter(v => v.status === 'done');
  }

  deleteList() {
    return this.list.filter(v => v.status === 'delete');
  }
}

const viewModel = createReactiveState(new TodoList());

const Index = () => {
  const refInput = useRef<HTMLInputElement>(null);
  useReactiveState(viewModel);

  const defaultList = viewModel.defaultList();
  const doneList = viewModel.doneList();
  const deleteList = viewModel.deleteList();

  useEffect(() => {
    viewModel.init();
  }, []);

  return (
    <div>
      <div style={{ paddingLeft: '40px', marginBottom: '20px' }}>
        <input type="text" ref={refInput} />
        <button
          style={{ marginLeft: '20px' }}
          type="button"
          onClick={() => {
            if (refInput.current) {
              const content = refInput.current.value;
              if (content) {
                viewModel.addTodo(content);
              }
            }
          }}
        >
          add todo
        </button>
      </div>

      <ul>
        default List:
        {defaultList.map(v => {
          return (
            <li key={v.id}>
              {v.content} status: {v.status}
              <button
                style={{ marginLeft: '20px' }}
                type="button"
                onClick={() => {
                  viewModel.finish(v.id);
                }}
              >
                finish
              </button>
            </li>
          );
        })}
      </ul>

      <ul>
        done List:
        {doneList.map(v => {
          return (
            <li key={v.id}>
              {v.content} status: {v.status}
              <button
                style={{ marginLeft: '20px' }}
                type="button"
                onClick={() => {
                  viewModel.finish(v.id);
                }}
              >
                finish
              </button>
            </li>
          );
        })}
      </ul>

      <ul>
        delete List:
        {deleteList.map(v => {
          return (
            <li key={v.id}>
              <del>
                {v.content} status: {v.status}
              </del>
            </li>
          );
        })}
      </ul>
    </div>
  );
};

export default Index;

在线例子可以点击这里查看
贴上源码 👉🏻 源码
期待宝子们的star⭐️,你的支持就是我最大的动力


其他文章
什么?在React中也可以使用vue响应式状态管理
clean-js | 自从写了这个辅助库,我已经很久没有加过班了…
clean-js | 在hooks的时代下,使用class管理你的状态
clean-js | 手把手教你写一个羊了个羊麻将版
写给前端的数据库入门 | 序
写给前端的数据库入门 | docker & 数据库
有没有一种可能,你从来都没有真正理解async
三分钟实现前端写JAVA这件事——装环境
三分钟实现前端写JAVA这件事——VS code