heluxjs / helux

A reactive atomic state engine for React like.

Home Page:https://heluxjs.github.io/helux/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

计算属性未响应界面变化

itmanyong opened this issue · comments

i18nMessage计算属性的值出乎意料之外,并未如同其他几个一样返回正确的值,写法是否有所问题
image

image

你好这个计算函数看起来并没有问题,你有打断点试试,能够进去吗,或者提供一个能够复现问题的codesandbox链接我看下

我打断点看了下,这个i18nMessage计算函数被触发了3次
第一次
image

第二次
image

第三次进入时,message为空了,你的逻辑什么时候把message 置为 {} 了呢
image

你仔细检查你的逻辑哈

我在你的链接的runConcent里添加了一个中间件,查看调用情况

import global from "./global";
import { run } from "concent";

run({ $$global: global }, {
  middlewares: [
    (midCtx, next)=>{
      console.log(midCtx);
      next();
    },
  ],
});

打印日志为

image

想看下 调用这两个方法的地方,发现你调用了个sm,但是仓库的index文件没有暴露sm,你是不是忘了push到git了呢

推荐build是打一份es源码,这样方便codesandbox调试,然后就是我找到原因了,问题出在这里
https://github.com/itmanyong/cxy-react-i18n/blob/master/src/i18n/watch.js

watch调用reducer方法时,流程中的数据其实还没有落到store

changeState(by reducer, setState) ---> trigger computed ---> trigger watch ---> save changedState to store

所以此时reducer里的调用再次触发的计算函数是拿不到最新的state的,你需要延迟一下

即将代码

import { MODEL_NAME, STORE_LANG_KEY } from '../configs/vars';
/**
 * 根据当前lang的存在性重置lang
 */
export const watch_lang_message = {
  fn: ({ lang, message }, o, f) => {
    if (!lang && Object.keys(message)[0]) {
      if (localStorage.getItem(STORE_LANG_KEY)) {
        f.refCtx.reducer[MODEL_NAME].setLang(localStorage.getItem(STORE_LANG_KEY));
      } else {
        f.refCtx.reducer[MODEL_NAME].setLang(Object.keys(message)[0]);
      }
    }
    if (lang && lang != o.lang) {
      localStorage.setItem(STORE_LANG_KEY, lang);
    }
  },
  depKeys: ['lang', 'message'],
  compare: true,
  immediate: true,
};

改为

import { MODEL_NAME, STORE_LANG_KEY } from '../configs/vars';
import { dispatch, reducer } from 'concent';

// 延迟到下一个事件循环执行reducer函数,确保watch流程中的改变数据先落地,之后触发的另外一轮computed函数
// 拿到的计算函数是正确的啦
const invokeReducer = (reducer, payload) => setTimeout(() => dispatch(reducer, payload), 0);

/**
 * 根据当前lang的存在性重置lang
 */
export const watch_lang_message = {
  fn: ({ lang, message }, o) => {
    if (!lang && Object.keys(message)[0]) {
      const setLang = reducer[MODEL_NAME].setLang;
      if (localStorage.getItem(STORE_LANG_KEY)) {
        invokeReducer(setLang, localStorage.getItem(STORE_LANG_KEY));
      } else {
        invokeReducer(setLang, Object.keys(message)[0]);
      }
    }
    if (lang && lang != o.lang) {
      localStorage.setItem(STORE_LANG_KEY, lang);
    }
  },
  depKeys: ['lang', 'message'],
  compare: true,
  immediate: true,
};

我准备下一版本把在f上绑一个函数 nextTickDispatch,方便用户安全的调用reducer方法

阿西吧!之前也怀疑过这个watch,因为独立出来store之后是正常的。。。请教下:build的es源码模式怎么配置呢

copy 一份 src 的源码 放 es目录即可

感谢!!!