Mobx 与 Material Grid 反应

Mobx React with Material Grid

我认为这是一个很简单的问题。我正在尝试在 React 中创建一个材质 ui 网格,并能够向其中添加行。我尝试了多种模式变体,但对我没有任何作用。我正在粘贴下面的示例,您可以找到代码 here.

import React from "react";
import "./styles.css";

import { observer, useObservable } from "mobx-react-lite";
import MaterialTable from "material-table";
import Button from "@material-ui/core/Button";

const columns = [
  { title: "First Name", field: "name" },
  { title: "Last Name", field: "surname" },
  { title: "Year of Birth", field: "birthYear", type: "numeric" },
  {
    title: "City of Birth",
    field: "birthCity",
    lookup: {
      34: "Haughton",
      63: "San Diego",
      88: "Henryetta"
    }
  }
];

const initialData = [
  { name: "Dak", surname: "Prescott", birthYear: 1993, birthCity: 34 }
];

const addData = [
  { name: "Troy", surname: "Aikman", birthYear: 1966, birthCity: 88 },
  { name: "Tony", surname: "Romo", birthYear: 1980, birthCity: 63 }
];
const App = observer(() => {
  const store = useObservable({
    data: initialData,
    index: 0,

    addRow() {
      if (store.index < store.data.length) {
        store.data.push(addData[store.index++]);
      }
    }
  });

  return (
    <div className="App">
      <MaterialTable
        columns={columns}
        data={store.data}
        title="Sample Material Table"
      />

      <Button onClick={() => store.addRow}>Add Row</Button>
    </div>
  );
});

export default App;

这只是一次尝试。我真正的 Mobx 存储是我在单独的文件中创建的,每个可观察的属性我都用@observable 注释,但在这一点上我绝对接受任何有效的东西。我已经让 Mobx 存储使用原生值(字符串和数字),但不使用对象数组。我希望我只是遗漏了一些细微差别。

好的,我查看了带有 material-table 标签的其他帖子,找到了问题的关键。我没有将元素推送到我的数据数组,而是将数组设置为附加了新元素的全新数组。

store.data = [...store.data, addData[store.index++]];

事实证明,即使进行了该更改,我上面的示例也无法正常工作,但是将数组修饰符更改为 return 新数组是解决方案的关键。

您关于修改存储的约定是正确的 - 通常,最好创建一个新数组或对象,并在合并新数据时将旧数据传播到新数据中。

我认为在你的情况下,你的 onClick 处理程序中有一个拼写错误。您不是在 Button 元素中调用它 - 您是 运行 一个箭头函数,但在内部您没有调用 addRow 方法!我已经为您重写了它,并且还切换到了 useLocalStore 挂钩,因为这是最近推荐使用的挂钩。

这也是复习 React 中从 onClick 属性调用函数的语法的好机会。

onClick={handleClick} // 传递一个函数的引用,当元素被点击时,React 会自动调用这个函数。您不需要手动调用它。换句话说,在这里放括号是错误的。

onClick={() => handleClick} // 创建一个内联箭头函数,React 会像上面那样自动 运行 这个函数。它将像普通函数一样执行每一行。它将到达标识符 handleClick 并且什么都不做,因为 handleClick 没有在您创建的新箭头函数中被调用。

onClick={() => handleClick()} // 与上面相同,您正在创建一个内联箭头函数。 React 会像上面那样 运行 这个箭头函数。它将执行每一行,然后调用你的函数,因为你已经用括号调用了它。

希望对您有所帮助!

顺便说一句,您需要验证从中获取新行的数据源是否能够接受您传入的索引。现在,如果您点击按钮两次以上,您会得到一个索引越界错误。但我假设您已经处理了那部分,所以我没有更改您的代码的那部分。

import React from "react";
import "./styles.css";

import { useObserver } from "mobx-react-lite";
import MaterialTable from "material-table";
import Button from "@material-ui/core/Button";
import { useLocalStore } from "mobx-react";

const columns = [
  { title: "First Name", field: "name" },
  { title: "Last Name", field: "surname" },
  { title: "Year of Birth", field: "birthYear", type: "numeric" },
  {
    title: "City of Birth",
    field: "birthCity",
    lookup: {
      34: "Haughton",
      63: "San Diego",
      88: "Henryetta"
    }
  }
];

const initialData = [
  { name: "Dak", surname: "Prescott", birthYear: 1993, birthCity: 34 }
];

const addData = [
  { name: "Troy", surname: "Aikman", birthYear: 1966, birthCity: 88 },
  { name: "Tony", surname: "Romo", birthYear: 1980, birthCity: 63 }
];
const App = () => {
  const store = useLocalStore(() => ({
    data: initialData,
    index: 0,
    addRow() {
      if (this.index < this.data.length) {
        this.data = [...this.data, addData[this.index++]];
      }
    }
  }));

  return useObserver(() => (
    <div className="App">
      <MaterialTable
        columns={columns}
        data={store.data}
        title="Sample Material Table"
      />

      <Button onClick={store.addRow}>Add Row</Button>
    </div>
  ));
};

export default App;