umijs / hox

State sharing for React components.
https://hox.js.org
MIT License
1.45k stars 100 forks source link

hox写了国际化的Hook,订阅方式易出现循环递归嵌套调用,导致组件初始化失败。 #23

Closed X-neuron closed 4 years ago

X-neuron commented 4 years ago

以下代码场景:主要实现 语言包加载完成后,在加载主界面,但主界面构建失败(其他组件都使用const {intl} = useLocaleModel()来国际化)。提示可能是出现内部的循环归调用失败..

如直接显示主界面,再切换语言则正常。

暂未上react 的同步模式,目前采用useEffect,setState的方式,来解决加载后刷新的逻辑。

这个方式hox国际化的逻辑 有问题么,还是这种内部订阅方式导致的问题 ??

import React, { useEffect } from 'react';
import useLocalesModel from '@/models/useLocales';
import { useSize } from '@umijs/hooks';
import { Spin } from 'antd';

function Locale({ children }) {
  const [body] = useSize(document.querySelector('body'));
  const { localeLoaded } = useLocalesModel();

  return (
    localeLoaded ? { children }
      : (
        <div
          style={{
            display: 'flex',
            justifyContent: 'center',
            alignItems: 'center',
            alignContent: 'center',
            width: body.width,
            height: body.height,
            margin: 'auto',
            textAlign: 'center'
          }}
        >
          <Spin tip="语言加载中..." size="large" />
        </div>
      )
  )
}
export default Locale;

useLocales:

import { useState, useRef, useEffect } from 'react';
import intl from 'react-intl-universal';
import request from 'umi-request';
import { usePersistFn } from '@umijs/hooks';
import _ from 'lodash';

// import scope from 'babel-plugin-console/scope.macro';
// import { useRequest } from '@umijs/hooks;'

import { createModel } from 'hox';

const Locales = [
  {
    name: '简体中文',
    value: 'zh-CN',
    icons: '🇨🇳'
  },
  {
    name: 'English',
    value: 'en-US',
    icons: '🇺🇸'
  }
];

function useLocales() {
  // 缓存json 防止重复请求
  console.log('useLocales running');
  const localeList = useRef(new Map());
  // 用ref 主要为了避免不必要的刷新。
  const curLang = useRef({ lang: null });

  const [localeLoaded, setLocaleLoaded] = useState(false);
  const [curLocale, setCurLocale] = useState(() => {
    const currentLocale = intl.determineLocale({
      urlLocaleKey: 'lang',
      cookieLocaleKey: 'lang',
      localStorageLocaleKey: 'lang'
    });
    const returnLocale = _.find(Locales, { value: currentLocale }) || Locales[0];
    return returnLocale;
  });

  const loadLocale = (locale) => {
    const currentLocale = locale.value;
    if (localeList.current.has(currentLocale)) {
      intl.init({
        currentLocale,
        locales: {
          [currentLocale]: localeList.current.get(currentLocale)
        }
      });
      curLang.current.lang = currentLocale
    } else {
      request.get(`public/locales/${currentLocale}.json`, {
        responseType: 'json'
      })
        .then(res => {
          intl.init({
            currentLocale,
            locales: {
              [currentLocale]: res
            }
          });
          localeList.current.set(currentLocale, res);
          curLang.current.lang = currentLocale;
        })
        .then(() => {
          setCurLocale(locale);
          setLocaleLoaded(true);
        })
    }
  };

  useEffect(() => {
    console.log('effect:', curLocale);
    loadLocale(curLocale);
  })

  const changeCurLocale = usePersistFn((key) => {
    if (curLang.current.lang === key) return;
    const returnLocale = _.find(Locales, { value: key }) || Locales[0];
    loadLocale(returnLocale);
  });

  return { Locales, curLocale, localeLoaded, changeCurLocale, intl }
}

export default createModel(useLocales);
X-neuron commented 4 years ago

消息报错列表:

useLocales running useLocales.jsx:27:10
effect: 
Object { name: "简体中文", value: "zh-CN", icons: "🇨🇳" }
useLocales.jsx:76:12
false 2 index.jsx:12:10
useLocales running useLocales.jsx:27:10
true index.jsx:12:10
Error: "Minified React error #31; visit https://reactjs.org/docs/error-decoder.html?invariant=31&args[]=object%20with%20keys%20%7Bchildren%7D&args[]= for the full message or use the non-minified dev environment for full errors and additional helpful warnings."
    React 9
    unstable_runWithPriority scheduler.production.min.js:19
    React 5
    e create-model.js:48
    notify container.js:24
    onUpdate create-model.js:34
    Executor executor.js:5
    xn react-reconciler.production.min.js:60
    sr react-reconciler.production.min.js:81
    Yr react-reconciler.production.min.js:161
    Bo react-reconciler.production.min.js:147
    Ho react-reconciler.production.min.js:147
    Ao react-reconciler.production.min.js:140
    yt react-reconciler.production.min.js:29
    unstable_runWithPriority scheduler.production.min.js:19
    pt react-reconciler.production.min.js:28
    yt react-reconciler.production.min.js:29
    mt react-reconciler.production.min.js:28
    Po react-reconciler.production.min.js:131
    Bn react-reconciler.production.min.js:70
    v useLocales.jsx:70
react-dom.production.min.js:209:194
    React 5
    unstable_runWithPriority scheduler.production.min.js:19
    React 4
    unstable_runWithPriority scheduler.production.min.js:19
    React 5
    e create-model.js:48
    notify container.js:24
    onUpdate create-model.js:34
    Executor executor.js:5
    xn react-reconciler.production.min.js:60
    sr react-reconciler.production.min.js:81
    Yr react-reconciler.production.min.js:161
    Bo react-reconciler.production.min.js:147
    Ho react-reconciler.production.min.js:147
    Ao react-reconciler.production.min.js:140
    yt react-reconciler.production.min.js:29
    unstable_runWithPriority scheduler.production.min.js:19
    pt react-reconciler.production.min.js:28
    yt react-reconciler.production.min.js:29
    mt react-reconciler.production.min.js:28
    Po react-reconciler.production.min.js:131
    Bn react-reconciler.production.min.js:70
    v useLocales.jsx:70
Error: "Minified React error #31; visit https://reactjs.org/docs/error-decoder.html?invariant=31&args[]=object%20with%20keys%20%7Bchildren%7D&args[]= for the full message or use the non-minified dev environment for full errors and additional helpful warnings."
    React 9
    unstable_runWithPriority scheduler.production.min.js:19
    React 5
    e create-model.js:48
    notify container.js:24
    onUpdate create-model.js:34
    Executor executor.js:5
    xn react-reconciler.production.min.js:60
    sr react-reconciler.production.min.js:81
    Yr react-reconciler.production.min.js:161
    Bo react-reconciler.production.min.js:147
    Ho react-reconciler.production.min.js:147
    Ao react-reconciler.production.min.js:140
    yt react-reconciler.production.min.js:29
    unstable_runWithPriority scheduler.production.min.js:19
    pt react-reconciler.production.min.js:28
    yt react-reconciler.production.min.js:29
    mt react-reconciler.production.min.js:28
    Po react-reconciler.production.min.js:131
    Bn react-reconciler.production.min.js:70
    v useLocales.jsx:70
react-reconciler.production.min.js:111:194
    Mr react-reconciler.production.min.js:111
    callback react-reconciler.production.min.js:127
    Lt react-reconciler.production.min.js:37
    Ir react-reconciler.production.min.js:114
    $o react-reconciler.production.min.js:153
    unstable_runWithPriority scheduler.production.min.js:19
    pt react-reconciler.production.min.js:28
    qo react-reconciler.production.min.js:149
    Ao react-reconciler.production.min.js:140
    yt react-reconciler.production.min.js:29
    unstable_runWithPriority scheduler.production.min.js:19
    pt react-reconciler.production.min.js:28
    yt react-reconciler.production.min.js:29
    mt react-reconciler.production.min.js:28
    Po react-reconciler.production.min.js:131
    Bn react-reconciler.production.min.js:70
    v useLocales.jsx:70
Error: Minified React error #31; visit https://reactjs.org/docs/error-decoder.html?invariant=31&args[]=object%20with%20keys%20%7Bchildren%7D&args[]= for the full message or use the non-minified dev environment for full errors and additional helpful warnings. react-dom.production.min.js:139:46

​
awmleer commented 4 years ago
image

这里 return {children} 有问题的吧?我理解你的场景应该是 return children ?这个报错应该是你的组件里逻辑出错了~

X-neuron commented 4 years ago

改 成children 逻辑OK 了。学习了,十分 感谢!