【问题标题】:Migration to Mobx 6: functional components aren't working with decorated observables迁移到 Mobx 6:功能组件不适用于装饰的 observables
【发布时间】:2021-04-13 14:10:03
【问题描述】:

我在从 Mobx 4 迁移到 Mobx 6 时遇到了问题。

我有一个功能组件,但更新 Mobx 后它停止工作。看起来商店不起作用。组件通过reaction 功能对可观察变量内的更改做出反应,但更改不会重新渲染。我制作了migration guide 中提供的所有内容,但组件的商店不起作用。

出于某种原因,如果我将功能组件更改为类组件,一切都会开始工作。但我真的无法理解发生这种情况的原因,也找不到任何解释这种行为的原因。

案例看起来像下面的例子。启用了实验性装饰器以及迁移指南中提供的任何其他内容。那么这种行为的原因是什么?如何在功能组件中实现正确逻辑?

interface User {
  name: string;
  age: number;
  info: {
    phone: string;
    email: string;
  };
}

const usersData: User[] = [
  {
    name: "Steve",
    age: 29,
    info: {
      phone: "+79011054333",
      email: "steve1991@gmail.com",
    },
  },
  {
    name: "George",
    age: 34,
    info: {
      phone: "+79283030322",
      email: "george_the_best_777@gmail.com",
    },
  },
  {
    name: "Roger",
    age: 17,
    info: {
      phone: "+79034451202",
      email: "rodge_pirat_yohoho@gmail.com",
    },
  },
  {
    name: "Maria",
    age: 22,
    info: {
      phone: "+79020114849",
      email: "bunnyrabbit013@gmail.com",
    },
  },
];

const getUsers = () => {
  return new Promise<User[]>((resolve) => {
    setTimeout(() => {
      resolve(usersData);
    }, 2000);
  });
};
class Store {
  @observable users: User[] = [];

  constructor() {
    makeObservable(this);
  }

  async init() {
    const users = await getUsers();
    this.setUsers(users);
  }

  @action setUsers(users: User[]) {
    this.users = users;
  }

  @action increaseUserAge(userIndex: number) {
    const users = this.users.map((u, k) => {
      if (k === userIndex) {
        u.age += 1;
      }
      return u;
    });
    this.setUsers(users);
  }

  @computed get usersCount(): number {
    return this.users.length;
  }
}

const store = new Store();

const UserList = observer(() => {
  React.useEffect(() => {
    store.init();
  }, []);

  const addOneUser = () => {
    const user = {
      name: "Jesica",
      age: 18,
      info: {
        phone: "+79886492224",
        email: "jes3331@gmail.com",
      },
    };
    store.setUsers([...store.users, user]);
  };

  return (
    <div className="App">
      <h4>Users: {store.usersCount}</h4>
      {store.users.length ? (
        <>
          <ul>
            {store.users.map((user, key) => (
              <li key={key}>
                Name: {user.name}, Age: {user.age}, Info:
                <div>
                  Phone: {user.info.phone}, Email: {user.info.email}
                </div>
                <button onClick={() => store.increaseUserAge(key)}>
                  Increase Age
                </button>
              </li>
            ))}
          </ul>
          <button onClick={addOneUser} disabled={store.usersCount >= 5}>
            Add one user
          </button>
        </>
      ) : (
        <p>Fetching users...</p>
      )}
    </div>
  );
});

function App() {
  return <UserList />;
}

export default App;

【问题讨论】:

  • 你为什么混合makeObservable和装饰器?这是使用 mobx 的两种不同方式。
  • @IvanV。对不起,但你错了。 mobx.js.org/…,第 2 页,引用:Leave all the decorators and call makeObservable(this) in the constructor. This will pick up the metadata generated by the decorators. This is the recommended way if you want to limit the impact of a MobX 6 migration.
  • 哦,我不知道decorators and makeAutoObservable`的选项存在。

标签: reactjs typescript mobx


【解决方案1】:

我已经用你的代码制作了Codesandbox example(尽管删除了类型),它工作正常。

在那里查看tsconfig.json,也许您忘记启用某些选项?

或者查看mobxmobx-react的版本是什么?

关于您如何使用increaseUserAge 操作只是一个小问题,就这么简单:

  @action increaseUserAge(user) {
    user.age += 1;
  }

在 jsx 中,您只需将整个用户传递到那里:

<button onClick={() => store.increaseUserAge(user)}>
  Increase Age
</button>

【讨论】:

    猜你喜欢
    • 2018-06-02
    • 2018-07-11
    • 1970-01-01
    • 2019-07-02
    • 1970-01-01
    • 2014-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多