React + Mobx 如何从不同的组件更改值并在各处显示更改?

React + Mobx How to change value from different components and show changes everywhere?

https://codesandbox.io/s/react-mobx-change-value-in-several-components-f2tuu

如何从不同的地方改变一个变量? 变量是一个,但它在不同的组件中分别发生变化,并且在一个组件中所做的这些更改不会反映在另一个组件中。

App.js

import AppStore from "./AppStore";
import { observer } from "mobx-react";
import SomeComponent from "./SomeComponent";

const store = AppStore();

const App = observer(() => {
  return (
    <div className="App">
      <div>
        <i>This is text in App:</i> {store.text}
      </div>
      <div>
        <button
          onClick={() => {
            store.changeText("This is text from App");
          }}
        >
          Change text from App
        </button>
      </div>

      <SomeComponent />

    </div>
  );
});

export default App;

SomeComponent.js

import React from "react";
import AppStore from "./AppStore";
import { observer } from "mobx-react";

const store = AppStore();

const SomeComponent = observer((props) => {
  return (
    <div>
      <div>
        <i>This is text in component:</i> {store.text}
      </div>
      <div>
        <button 
            onClick={() => store.changeText("This is text from component")}
        >
          Change text from component
        </button>
      </div>
    </div>
  );
});

export default SomeComponent;

AppStore.js

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

export default function AppStore() {
  return makeObservable(
    {
      text: "Initial text",
      changeText(data) {
        this.text = data + ": " + new Date().toLocaleTimeString();
      }
    },
    {
      text: observable,
      changeText: action
    }
  );
}

在您的 App 组件中,您通过此代码 const store = AppStore(); 创建了一个对象变量 store。然后你使用它,显示它,改变它等等。稍后在 SomeComponent 组件中,您通过 const store = AppStore(); 创建了一个新变量 store。即使变量名称相同并使用对象,这些也是 2 个不同的变量。因此,为什么更新一个不更新另一个。在 DOM 内部,它们是不同的对象。要修复它而不是在 SomeComponent 中创建新对象,只需从父组件传递 store 即可。在 App 中,渲染 SomeComponent 时将 store 变量传递给它

<SomeComponent store={store} />

在你的SomeComponent里面从道具中取出并使用它

import React from "react";
import { observer } from "mobx-react";

const SomeComponent = observer(({ store }) => {
  return (
    <div>
      <div>
        <i>This is text in component:</i> {store.text}
      </div>
      <div>
        <button onClick={() => store.changeText("This is text from component")}>
          Change text from component
        </button>
      </div>
    </div>
  );
});

export default SomeComponent;

这样两个组件都可以更改相同的变量数据。

编辑。我分叉了你的项目并编辑了代码以匹配我在这里发布的内容,这样你就有了一个活生生的例子来分析。 https://codesandbox.io/s/react-mobx-change-value-in-several-components-forked-4c7uk?file=/src/SomeComponent.js

我找到了 React Context 的解决方案。 很抱歉没有立即在此处添加。 不幸的是,很难理解 Mobx 文档。

https://codesandbox.io/s/react-mobx-change-value-in-several-components-forked-using-react-context-e1mjh

首先,我们需要创建上下文并创建提供者:

https://codesandbox.io/s/react-mobx-change-value-in-several-components-forked-using-react-context-e1mjh?file=/src/AppStoreProvider.js

import { useLocalStore } from "mobx-react";
import React from "react";
import AppStore from "./AppStore";

export const AppStoreContext = React.createContext();

export const AppStoreProvider = ({ children }) => {
  const store = useLocalStore(AppStore);
  return (
    <AppStoreContext.Provider value={store}>
      {children}
    </AppStoreContext.Provider>
  );
};

export const UseAppStore = () => React.useContext(AppStoreContext);

export default AppStoreProvider;

其中 AppStore.js 是:

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

export default function AppStore() {
  return makeObservable(
    {
      text: "Initial text",
      changeText(data) {
        this.text = data + ": " + new Date().toLocaleTimeString();
      }
    },
    {
      text: observable,
      changeText: action
    }
  );
}

https://codesandbox.io/s/react-mobx-change-value-in-several-components-forked-using-react-context-e1mjh?file=/src/AppStore.js

然后,我们需要用 :

在 index.js 中包装我们的主渲染
import { StrictMode } from "react";
import ReactDOM from "react-dom";
import AppStoreProvider from "./AppStoreProvider";

import App from "./App";

const rootElement = document.getElementById("root");
ReactDOM.render(
  <AppStoreProvider>
    <App />
  </AppStoreProvider>,
  rootElement
);

https://codesandbox.io/s/react-mobx-change-value-in-several-components-forked-using-react-context-e1mjh?file=/src/index.js

然后我们可以使用上下文:

import "./styles.css";
import React from "react";
import { UseAppStore } from "./AppStoreProvider";
import { observer } from "mobx-react";
import SomeComponent from "./SomeComponent";

const App = observer(() => {
  const store = UseAppStore();

  return (
    <div className="App">
      <div>
        <i>This is text in App:</i> {store?.text}
      </div>
      <div>
        <button
          onClick={() => {
            store.changeText("This is text from App");
          }}
        >
          Change text from App
        </button>
      </div>

      <SomeComponent />

    </div>
  );
});

export default App;

https://codesandbox.io/s/react-mobx-change-value-in-several-components-forked-using-react-context-e1mjh?file=/src/App.js

或者像这样:

import { useContext } from "react";
import { AppStoreContext } from "./AppStoreProvider";
import { observer } from "mobx-react";

const SomeComponent = observer((props) => {
  const store = useContext(AppStoreContext);

  return (
    <div>
      <div>
        <i>This is text in component:</i> {store.text}
      </div>
      <div>
        <button onClick={() => store.changeText("This is text from component")}>
          Change text from component
        </button>
      </div>
    </div>
  );
});

export default SomeComponent;

https://codesandbox.io/s/react-mobx-change-value-in-several-components-forked-using-react-context-e1mjh?file=/src/SomeComponent.js

希望对某人有用