跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • 希望把逻辑和视图分开,逻辑类的实例改变后, react 如何通知组件更新?
未分類
15 5 月 2020

希望把逻辑和视图分开,逻辑类的实例改变后, react 如何通知组件更新?

希望把逻辑和视图分开,逻辑类的实例改变后, react 如何通知组件更新?

資深大佬 : xiaoming1992 5

由于一些原因,我希望把逻辑和视图分开,如下列伪代码所示,大佬能说说有什么好的解决方案吗?关键字就行,谢谢了!

(ps: react class component 也是视图和逻辑混在一个类里面, 不太希望这样, 还是我的使用姿势不对?)

import React, { useEffect } from "react"  class Person {   name: string    age: number    friends: Person[] }  class Family {   datas: Person[] }  class Village {   datas: Family[] }  // 以上的类为纯逻辑类, 仅进行数据处理, 不含视图渲染  function View() {   const village = new Village()    useEffect(() => {     // Village 泛指一些层级很深的类     // 这儿有一些交互, 然后会修改 village 的一些属性, 和属性的后代属性     // 问题是, 修改了 village 之后, 怎么通知组件更新呢...   }, [village])    return  village.datas.map((family) => family.datas.map((person) => render(person))) } 

大佬有話說 (10)

  • 資深大佬 : iamppz

    用 state hook,useState(new Village())

  • 主 資深大佬 : xiaoming1992

    @iamppz useState 也没用,当我用 village 自身的方法修改了自身的数据的时候,仍然不会触发组件更新

  • 資深大佬 : WittBulter

    当你在 `React FC` 中调用 `setState` 不同的值会就触发一次更新,或者 `Props` 改变也会触发,基于这个原理你可以写一个非常简单 hooks 来解决这件事:

    “`
    const [, setState] = useState({})
    const forceUpdate = useCallback(() => setState({}), [])
    “`

    我在 codesendbox 上给你写了一个 hooks 的例子: https://codesandbox.io/s/force-update-react-7e8zs?file=/src/app.js

  • 主 資深大佬 : xiaoming1992

    @iamppz 比方说

    const village = new Village()

    const familyA = village.datas[3]

    const personS = familyA.datas[4]

    personS.age += 1

    这样的情况,我目前的处理是,在每个操作时,手动通知组件更新,可是这也太傻了…

    (ps: 可以全量更新 village, 如 setVillage(newVillage), 但是对于复杂的, 数组和对象混杂的对象, 这样做很累, 还丑)

  • 主 資深大佬 : xiaoming1992

    @WittBulter 谢谢,我现在就是这样处理的,可是一方面到处都是 forceUpdate,有点丑,另一方面全程需要手动管理,感觉回到了 jQ,很难受…

  • 主 資深大佬 : xiaoming1992

    @WittBulter 你的封装比我的帅,你看我的:

    const [uselessFlag, setUselessFlag] = useState(false)
    const updataComponent = useCallback(() => {
    setUselessFlag(!uselessFlag)
    }, [uselessFlag])

  • 資深大佬 : iamppz

    @xiaoming1992 state 应该是不能直接修改的,你可以用 immutability-helper 修改并拿到 village 的一个新的克隆对象,然后再调用 setState 触发页面的刷新。

    另外如果目的只是视图和逻辑分离的话,是否可以考虑将 reducer 函数从视图文件中分离出去:

    例如 biz.js
    “`
    function reducer(state, action) {
    switch (action):
    case ‘xxx’:
    // immutability-helper
    update(state, {
    x: {y: {z: {$set: 7}}},
    });
    break;
    default:
    break;
    return {…state};
    }
    “`

    视图中:
    “`
    function View() {
    const [data, dispatch] = useReducer(reducer, new Village());
    return <span>{JSON.stringify(data)}</span>;
    }
    “`

  • 資深大佬 : theprimone

    forceUpdate 可以再封装一个像 setState 的功能嘛,触发了自动调用 forceUpdate 。

  • 主 資深大佬 : xiaoming1992

    @iamppz reducer 确实挺好,只是不太喜欢这种风格,貌似是目前的最优方案了

    @theprimone 对象层级比较深,对象中有数组,数组里面是对象,对象下边还有数组,深层对象的属性变动不好监听,可能又会回到下面这种样子:
    setData({
    …data,
    key: [
    …data[key],
    val,
    ],
    })
    这仅仅一层就已经这么丑了,要是三四层,就丑的没边了,而自动调用,前提还是得监听数据的变化,可能得试试 proxy

  • 資深大佬 : theprimone

    proxy 还没玩过,直接点比较差异的话,fast-deep-equal 应该可以。

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具