使用umi的useModel踩坑

2,277 阅读1分钟

前言

在使用umi的hook——useModel时,setState的时候,视图不更新。

具体问题

目录结构

src
│  ├─ .umi
│  ├─ models
│  │  └─ users.ts
│  └─ pages
│     ├─ ModifyValue.tsx
│     ├─ index.less
│     └─ index.tsx

代码

//users.ts
import { useState } from 'react';

const useUsers = () => {
  const [datas, setDatas] = useState([
    {
      id: 1,
      name: 'john',
      gender: 'm',
    },
    {
      id: 2,
      name: 'mary',
      gender: 'f',
    },
  ]);
  return {
    datas,
    setDatas,
  };
};

export default useUsers;

//ModifyValue.ts
import React from 'react';
import { useModel } from 'umi';

export default function ModifyValue() {
  const { datas, setDatas } = useModel('users', (ret) => ({
    datas: ret.datas,
    setDatas: ret.setDatas,
  }));
  const updateFieldChanged = () => {
    let newArr = [...datas]; // copying the old datas array
    newArr[0].name = '123';
    setDatas(newArr);
  };
  return <button onClick={updateFieldChanged}>modifyValue</button>;
}

//index.tsx
import { useEffect } from 'react';
import { useModel } from 'umi';
import ModifyValue from './modifyValue';

export default function IndexPage() {
  const { datas } = useModel('users', (ret) => ({
    datas: ret.datas,
  }));

  return (
    <div>
      {JSON.stringify(datas)}
      <ModifyValue />
    </div>
  );
}

具体表现为: useModel坑1.png

useModel分析图 .png

问题分析:

  1. useModel的实现

useModel踩坑2.png

2.分析在代码执行中state是如何变化的

useModel分析图 .png

因为let newArr = [...datas]只是进行了浅复制,所以只复制了datas中存放的地址值,所以当使用let newArr=[...data]去修改的时候是修改地址1当中存在的值,最后newArrdatas在比较的时候没有差别,所以就没有触发更新

解决方案

  const updateFieldChanged = () => {
    let newArr = [...datas]; // copying the old datas array
    newArr[0] = {
      ...newArr[0],
      name: '123',
    }; //拷贝对象
    setDatas(newArr);
  };