微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么在作为引用传递时更新 MobX 可观察属性不起作用

如何解决为什么在作为引用传递时更新 MobX 可观察属性不起作用

我正在试验 MobX,并想了解有关可观察更新的基本知识。

在以下代码中,store.parentState.counterParent 传递到 ChildParentChild 都有一个 increment 按钮,用于更新 counter

但是,只有 Parent 的按钮会更新计数器。

这是为什么?另外,我们可以让子按钮工作吗?

import React from "react";
import { observable,configure } from 'mobx'
import { observer } from 'mobx-react-lite'

const store = observable({
  parentState: {
    counter: 0
  }
})
const Parent = observer((props) => {
  const increment = () => { store.parentState.counter += 1; };
  return (
    <div>
      <span>Parent: {store.parentState.counter}</span>
      <button onClick={increment}>increment</button>
      <Child parentCounter={store.parentState.counter} />
    </div>
  );
});
const Child = observer(({parentCounter}) => {
  const increment = () => { parentCounter +=1 ; };
  return (
    <div>
      <span>Child</span>
      <button onClick={increment}>increment</button>
    </div>
  );
});

configure({
  enforceActions: "never",})

export default Parent;

Live demo

编辑:
为了澄清一下,我知道在这个例子中,孩子可以直接更新商店,所以传递对 counter 的引用没有多大意义。或者,如评论中所建议的,可以将 store 传递给孩子。
但是,如前所述,我正在试验 MobX,并想了解 为什么(以及它是否可以工作)。

解决方法

[编辑]:您直接在道具中传递 counter。我假设因为它是一个原始类型,所以它作为值传递(而不是 ref 作为对象),因此没有任何绑定到商店。传递 appState 节点效果很好,如 this Stackblitz example 所示。这是以防万一的代码:

import React from "react";
import { render } from "react-dom";
import { observable } from "mobx";
import { observer } from "mobx-react-lite";

const store = observable({
  appState: {
    counter: 0
  }
});

const App = observer(() => {
  const increment = () => (store.appState.counter += 1);

  return (
    <div>
      Counter: {store.appState.counter}
      <br />
      <button onClick={increment}>Increment</button>
      <hr />
      <AppChild appState={store.appState} />
    </div>
  );
});

const AppChild = observer(({ appState }) => {
  const increment = () => (appState.counter += 1);
  return (
    <>
      Counter: {store.appState.counter}
      <br />
      <button onClick={increment}>Increment from child</button>
    </>
  );
});

render(<App />,document.getElementById("root"));

我不了解 MobX,但由于您的商店是全球性的,就像在其他商店管理器中一样,将值从您的父级传递给用 observer() 包装的组件是没有意义的。只是做以下工作:

import React from "react";
import { observable,configure } from "mobx";
import { observer } from "mobx-react-lite"; // 6.x or mobx-react-lite@1.4.0
import "./styles.css";

const store = observable({
  parentState: {
    counter: 0
  }
});
const Parent = observer((props) => {
  const increment = () => {
    store.parentState.counter += 1;
  };
  return (
    <div>
      <span>Parent: {store.parentState.counter}</span>
      <button onClick={increment}>increment</button>
      <Child parentCounter={store.parentState.counter} />
      <Child2 updateCounter={increment} />
    </div>
  );
});

const Child = observer(() => {
  const increment = () => {
    console.log(store.parentState.counter);
    store.parentState.counter += 1;
  };
  return (
    <div>
      <span>Child</span>
      <button onClick={increment}>increment</button>
    </div>
  );
});

const Child2 = ({updateCounter}) => {
  return (
    <div>
      <span>Child2</span>
      <button onClick={updateCounter}>increment</button>
    </div>
  );
}

configure({
  enforceActions: "never"
});

export default Parent;

我添加了一个 Child2 组件来向您展示如何使用父方法通过未用 observer() 包装的组件更新您的商店。

现在,因为这对我来说毫无意义,所以我不知道可能有解决方案可以做到这一点,但我没有看到您需要这样做的任何情况。

,

MobX documentation 中找到答案:MobX 跟踪属性访问,而不是值。

MobX 对任何现有的 observable 属性做出反应 被跟踪函数的执行。

  • "reading" 是取消引用一个对象的属性,这可以做到 通过“点入”它(例如user.name)或使用括号 符号(例如 user['name']todos[3])。
  • “跟踪功能”computed 的表达式,observer React 函数的渲染 组件,基于 render() 的 React 类的 observer 方法 组件,以及作为第一个参数传递给的函数 autorunreactionwhen
  • “during” 意味着只有那些可观察的 在函数执行时读取的被跟踪。它没有 无论这些值是直接使用还是间接使用 跟踪功能。但是从“产生”的东西 不会跟踪函数(例如 setTimeoutpromise.thenawait 等)。

换句话说,MobX 不会对:

  • 从 observable 中获得的值,但在跟踪范围之外 功能
  • 在异步调用的代码中读取的 Observable 块

因此,在子进程中传递 store.parentState 并访问 counter 将使其工作。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。