Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] model 插件导出纯对象出现 xxx.ValueOf is not a function 问题 #12175

Closed
Baoyx007 opened this issue Mar 5, 2024 · 5 comments
Closed

Comments

@Baoyx007
Copy link
Contributor

Baoyx007 commented Mar 5, 2024

What happens?

使用 model 出现如下报错 xxx.ValueOf is not a function

TypeError: a.valueOf is not a function
    at equal (http://192.168.70.15:8000/static/cem-sales-pc/umi.js:131596:58)
    at equal (http://192.168.70.15:8000/static/cem-sales-pc/umi.js:131609:12)
    at handler (http://192.168.70.15:8000/static/cem-sales-pc/umi.js:61623:123)
    at http://192.168.70.15:8000/static/cem-sales-pc/umi.js:61522:11
    at Set.forEach (<anonymous>)
    at Dispatcher.update (http://192.168.70.15:8000/static/cem-sales-pc/umi.js:61519:34)
    at Object.onUpdate [as current] (http://192.168.70.15:8000/static/cem-sales-pc/umi.js:61574:22)
    at http://192.168.70.15:8000/static/cem-sales-pc/umi.js:61552:17
    at invokePassiveEffectCreate (http://192.168.70.15:8000/static/cem-sales-pc/umi.js:250909:20)
    at HTMLUnknownElement.callCallback (http://192.168.70.15:8000/static/cem-sales-pc/umi.js:231372:14)
    at Object.invokeGuardedCallbackDev (http://192.168.70.15:8000/static/cem-sales-pc/umi.js:231421:16)
    at invokeGuardedCallback (http://192.168.70.15:8000/static/cem-sales-pc/umi.js:231483:31)
    at flushPassiveEffectsImpl (http://192.168.70.15:8000/static/cem-sales-pc/umi.js:250996:9)
    at unstable_runWithPriority (http://192.168.70.15:8000/static/cem-sales-pc/umi.js:277106:12)
    at runWithPriority$1 (http://192.168.70.15:8000/static/cem-sales-pc/umi.js:238703:10)
    at flushPassiveEffects (http://192.168.70.15:8000/static/cem-sales-pc/umi.js:250869:14)
    at http://192.168.70.15:8000/static/cem-sales-pc/umi.js:250746:11
    at workLoop (http://192.168.70.15:8000/static/cem-sales-pc/umi.js:277055:34)
    at flushWork (http://192.168.70.15:8000/static/cem-sales-pc/umi.js:277028:14)
    at MessagePort.performWorkUntilDeadline (http://192.168.70.15:8000/static/cem-sales-pc/umi.js:276795:27)

定位后发现, 如果 model 返回的是纯对象, 这个对象没有 valueOf 方法就会出错

Mini Showcase Repository(REQUIRED)

export default function Demo() {
  let a = Object.create({},{a:Random()})
  let b = Object.create({},{b:Random()})
  a.b = b
  return {
    a,
    update:()=>{
      a = {}
    }
  }
}

在线 demo

Context

  • Umi Version: 4.1.2
  • Node Version:
  • Platform:
Copy link

github-actions bot commented Mar 5, 2024

由于缺乏足够的信息,我们暂时关闭了该 Issue。请修改(不要回复) Issue 提供最小重现以重新开启。谢谢。

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Mar 5, 2024
@Baoyx007
Copy link
Contributor Author

Baoyx007 commented Mar 6, 2024

只要接口返回的 json 是直接当成 model 返回时, 非常容易复现

@fz6m
Copy link
Member

fz6m commented Mar 7, 2024

在你的 demo 复现里,这段代码:

  let a = Object.create({}, { a: Math.random() });
  let b = Object.create({}, { b: Math.random() });
  a.b = b;

在浏览器控制台运行了一下,会直接报错的,这是一段错误的代码。

只要接口返回的 json 是直接当成 model 返回时, 非常容易复现

如有问题,需要给一个最小复现。

@Baoyx007
Copy link
Contributor Author

Baoyx007 commented Mar 7, 2024

不好意思, 搞错了. 已更新例子

问题应该就 useModel() 方法的第二个参数. 在第二次渲染的时候, 会对新旧 2 个对象调用下面这个 isEqual 方法, 而 isEqual 又会调用 valueOf 方法导致报错.

if (!isEqual(currentState, previousState)) {

@fz6m
Copy link
Member

fz6m commented Mar 8, 2024

你新给的 codesandbox 例子里,这段代码:

  const { a } = useModel('index', ({ a }) => {
    a;
  });

是没有返回值的,在 js 里返回值必须使用 return { a } ,如果要省略 return ,对于 object 类型的需要添加括号,比如 () => ({ a }) / () => 1 / () => [] ,更多方式请自行查找学习。

如果改成 return { a } 就可以正常运行了。

至于你提到的 valueOf 问题:

在各种 react 全局状态管理方案里,use model 这个方案是属于使用原生 context 的原生方案,比较轻量,但 context 中的数据只要有任何值更新了,整个 context 下面的内容都会重渲染,这里 use model 在每次数据更新时使用 equal 对比方法来避免一部分重渲染的问题,所以就需要你的对象拥有能对比值的实现。

Object.create 是创建纯对象的方法,不是一般的对象,创建一个对象应该使用 {} ,纯对象一般用于需要自行实现原生方法避免冲突(如 toString)或特殊不需要继承方法的安全场景,99% 的情况你并不需要纯对象,所以当你有需求需要使用纯对象时,应该自行实现各种你需要的继承方法,如果你需要使用 use model ,就需要最少实现 valueOf ,但我并不确定在 react 、use model 、其他的三方库代码中是否还会使用其他继承方法,所以如果你需要使用纯对象,为了避免在应用中传递、使用时出现问题,所有可能需要的方法都应该自己实现。

@umijs umijs locked as resolved and limited conversation to collaborators Mar 8, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants