原文链接: mobx-react 类似vuex的react版 响应式状态管理

上一篇: 统计自己文章数目 cheerio

下一篇: mobx-react 多个store 和 全局状态

风格上和react的不可变数据有些不太一样, 但是使用上确实和vuex很像

安装

https://github.com/mobxjs/mobx-react

yarn add mobx mobx-react

简单计数器

up-f9cb4f8f9eb1c6138ace1a50a53cbe22d89.png

import React from 'react';
import { useLocalStore, useObserver } from 'mobx-react';

export default () => {
  const todo = useLocalStore(() => ({
    count: 0,
    inc() {
      this.count++;
    },
  }));
  return useObserver(() => <h1 onClick={todo.inc}>{todo.count}</h1>);
};

计算属性, 初始值和prop的

import React, { useState } from 'react';
import {
  observer,
  useAsObservableSource,
  useLocalStore,
} from 'mobx-react-lite';

interface CounterProps {
  multiplier: number;
}

const Counter = observer(function Counter(props: CounterProps) {
  const observableProps = useAsObservableSource(props);
  const store = useLocalStore(() => ({
    count: 1,
    get multiplied() {
      return observableProps.multiplier * this.count;
    },
    inc() {
      this.count += 1;
    },
  }));

  return (
    <div>
      count :{store.count} Multiplied count: <span>{store.multiplied}</span>
      <button id="inc" onClick={store.inc}>
        Increment
      </button>
    </div>
  );
});

export default () => {
  const [multiplier, setMultiplier] = useState(1);

  return (
    <div>
      multiplier:{multiplier}
      <button onClick={() => setMultiplier(v => v + 1)}>add multiplier</button>
      <Counter multiplier={multiplier}></Counter>
      <Counter multiplier={multiplier + 1}></Counter>
    </div>
  );
};

一个简单的todo

import React, { FC } from 'react';
import { observer, useLocalStore } from 'mobx-react'; // 6.x or mobx-react-lite@1.4.0

const createTodos = (init: string[]) => {
  return init.reduce((pre, cur) => {
    pre[cur] = true;
    return pre;
  }, {} as Record<string, boolean>);
};

const Todo: FC<{
  done: boolean;
  text: string;
  onToggle: (todo: string) => void;
}> = ({ done, text, onToggle }) => {
  return (
    <div>
      done:{done.toString()},text:{text}
      <button onClick={() => onToggle(text)}>change</button>
    </div>
  );
};

const TodoList: FC<{ initialTodos: string[] }> = observer(
  ({ initialTodos }) => {
    const todoRef = React.useRef();
    const store = useLocalStore(() => ({
      todos: createTodos(initialTodos) as Record<string, boolean>,
      get pendingTodos() {
        return Object.keys(store.todos).filter(
          todo => store.todos[todo] === false
        );
      },
      get doneTodos() {
        return Object.keys(store.todos).filter(
          todo => store.todos[todo] === true
        );
      },
      addTodo: () => {
        store.todos[todoRef.current.value] = false;
        todoRef.current.value = '';
      },
      toggleTodo: (todo: string) => {
        store.todos[todo] = !store.todos[todo];
      },
    }));

    const renderTodo = (done: boolean) => todo => (
      <Todo key={todo} done={done} text={todo} onToggle={store.toggleTodo} />
    );

    return (
      <div>
        <h3>pendingTodos</h3>
        {store.pendingTodos.map(renderTodo(false))}
        <h3>doneTodos</h3>
        {store.doneTodos.map(renderTodo(true))}
        <br />
        <input ref={todoRef} />
        <button onClick={store.addTodo}>Add todo</button>
      </div>
    );
  }
);

export default () => {
  return <TodoList initialTodos={['hello', 'world']} />;
};

Logo

前往低代码交流专区

更多推荐