PPPPPPP пре 5 месеци
родитељ
комит
942e44e12b

+ 1 - 0
public/index.html

@@ -30,6 +30,7 @@
       <meta name="twitter:site" content="website">
       <meta name="twitter:url" content="https://24680.com">
 
+    <meta name="mobile-web-app-capable" content="yes">
     <meta name="apple-mobile-web-app-capable" content="yes">
     <meta name="apple-mobile-web-app-status-bar-style" content="black">
 

+ 4 - 4
src/components/GameList/index.jsx

@@ -1,5 +1,5 @@
 import styles from "@components/GameList/styles.module.scss";
-import React, {useEffect, useRef, useState} from "react";
+import React, {Fragment, useEffect, useRef, useState} from "react";
 import GameItem, {GameImgAspectRatio, GameItemImgAspectRatio} from "@components/GameItem";
 import {REQ_STATUS} from "@api/config";
 import SmallLoading from "@components/SmallLoading";
@@ -262,9 +262,9 @@ const GameList=({data,status,reqMore,user})=>{
                             // }
                         }
                         return (
-                            <>
+                            <Fragment key={`gl_${row}`}>
                                 {renderRoom(row,len)}
-                                <div key={row} className={styles.list_row} style={rowStyle}>
+                                <div className={styles.list_row} style={rowStyle}>
                                     {
                                         rowArr.map((item, col) => {
                                             let itemStyle={}
@@ -288,7 +288,7 @@ const GameList=({data,status,reqMore,user})=>{
                                         })
                                     }
                                 </div>
-                            </>
+                            </Fragment>
                         )
                     })
                 }

+ 3 - 3
src/components/GameSmallList/index.jsx

@@ -1,5 +1,5 @@
 import styles from "@components/GameSmallList/styles.module.scss";
-import React, {useRef, useEffect, useState} from "react";
+import React, {Fragment, useRef, useEffect, useState} from "react";
 import {NavLink} from "react-router-dom";
 import symbol from "@assets/symbol-defs.svg";
 import {LazyLoadImage} from "react-lazy-load-image-component";
@@ -353,7 +353,7 @@ const GameSmallList=({data,user})=>{
                     <div className={styles.grid_row_con} style={gridStyle}>
                         {
                             rowlist.map((ritem,rindex)=>{
-                                if (ritem==null)return (<></>);
+                                if (ritem==null)return (<Fragment key={`row_skip_${rindex}`}/>);
                                 return (
                                     <div key={rindex} className={styles.grid_row}>
                                         {
@@ -372,7 +372,7 @@ const GameSmallList=({data,user})=>{
                                                 let gridNum=item.gridNum!=null?item.gridNum:1;
                                                 // gridNum=Math.floor(Math.random()*3)+1;
                                                 let whStyle=gridInfo[gridNum];
-                                                if (whStyle==null)return (<></>);
+                                                if (whStyle==null)return (<Fragment key={`item_skip_${index}`}/>);
                                                 return (
                                                     <GameItem whStyle={whStyle} key={index} data={item} handleRoom={(e,data)=>{
                                                         handleSelect(e,data);

+ 11 - 3
src/features/mainSlice.js

@@ -829,14 +829,20 @@ const getRouteFromPath=(state,path)=>{
     }
     return route;
 }
+const EMPTY_ROUTE={};
 export const getRoute=(path)=>(state)=>{
     // let route=routesMap(state)[path];
     let route=getRouteFromPath(state,path);
-    if (route==null)return {};
+    if (route==null)return EMPTY_ROUTE;
     return route;
 }
+// memoize getRouteChain by (mapRef, path) to avoid returning new arrays each call
+const _routeChainCache=new WeakMap();
 export const getRouteChain=(path)=>(state)=>{
     let map=routesMap(state);
+    let perMap=_routeChainCache.get(map);
+    if (perMap==null){ perMap={}; _routeChainCache.set(map,perMap); }
+    if (perMap[path]!=null) return perMap[path];
     let list=[];
     let getChain=(cpath)=>{
         let route=map[cpath];
@@ -848,6 +854,7 @@ export const getRouteChain=(path)=>(state)=>{
         }
     }
     getChain(path);
+    perMap[path]=list;
     return list;
 }
 export const getRouteStyles=(state)=>{
@@ -1058,9 +1065,10 @@ export const getUserVip=(state)=>{
     if (userInfo&&userInfo.vip!=null)return userInfo.vip;
     return 0;
 }
-export const getVipConfig=(state)=>state.main.vipConfig||[];
+const EMPTY_ARR_MAIN=[];
+export const getVipConfig=(state)=>state.main.vipConfig||EMPTY_ARR_MAIN;
 export const getHolidaysGiftInfo=(state)=>state.main.holidaysGiftInfo||null;
-export const getSlotsPartner=(state)=>state.main.slotsPartner||[];
+export const getSlotsPartner=(state)=>state.main.slotsPartner||EMPTY_ARR_MAIN;
 export const getHolidaysActInfo=(state)=>state.main.holidaysActInfo||null;
 export const getIsBindPhone=(state)=>{
     let userInfo=state.main.userInfo;

+ 7 - 1
src/features/pageSlice.js

@@ -206,9 +206,15 @@ const collectGameItems=(pageData)=>{
     if (pageData){ for (const k in pageData) visit(pageData[k]); }
     return list;
 }
+// memoize by pageData reference so useSelector won't see "new array" each call
+let _orderedGamesPageRef=null;
+let _orderedGamesCache=[];
 export const getOrderedGames=(state)=>{
     const pageData=state.page&&state.page.pageData;
-    return collectGameItems(pageData);
+    if (pageData===_orderedGamesPageRef) return _orderedGamesCache;
+    _orderedGamesPageRef=pageData;
+    _orderedGamesCache=collectGameItems(pageData);
+    return _orderedGamesCache;
 }
 export const getPopularGames=(state)=>{
     const pageData=state.page&&state.page.pageData;

+ 3 - 2
src/features/paySlice.js

@@ -673,8 +673,9 @@ export const getKycTypes=(state)=>{
 //gift stubs (for WPromotion2)
 export const getFirstPayGift=(state)=>state.pay.firstPayGift;
 export const getFirstPayGiftClaimStatus=(state)=>state.pay.status?.FirstPayGiftClaim;
-export const getDailyGift=(state)=>state.pay.dailyGift||{};
-export const getDailyRechargeGift=(state)=>state.pay.dailyRechargeGift||{};
+const EMPTY_OBJ_PAY={};
+export const getDailyGift=(state)=>state.pay.dailyGift||EMPTY_OBJ_PAY;
+export const getDailyRechargeGift=(state)=>state.pay.dailyRechargeGift||EMPTY_OBJ_PAY;
 export const getRecallGiftInfo=(state)=>state.pay.recallGiftInfo;
 export const getRecallGiftState=(state)=>state.pay.recallGiftState;
 export const getRecallGiftClaimStatus=(state)=>state.pay.status?.RecallGiftClaim;

+ 16 - 11
src/features/turnplateSlice.js

@@ -147,19 +147,24 @@ export const getTotalAmount=(state)=>{
 export const getIsHelp=(state)=>{
     return state.turnplate.helpdone;
 }
+const EMPTY_NUMBERS=[];
+let _numbersInputRef=null;
+let _numbersCache=EMPTY_NUMBERS;
 export const getNumbers=(state)=>{
-    if (state.turnplate.numbers){
-        let numbers=state.turnplate.numbers;
-        let temp=numbers.slice(0);
-        let random=[];
-        for (let i = 0; i <20 ; i++) {
-            let rand=Math.floor(Math.random()*temp.length);
-            random.push(temp[rand]);
-            temp.splice(rand,1);
-        }
-        return random;
+    const numbers=state.turnplate.numbers;
+    if (!numbers) return EMPTY_NUMBERS;
+    if (numbers===_numbersInputRef) return _numbersCache;
+    let temp=numbers.slice(0);
+    let random=[];
+    for (let i = 0; i <20 ; i++) {
+        if (temp.length===0)break;
+        let rand=Math.floor(Math.random()*temp.length);
+        random.push(temp[rand]);
+        temp.splice(rand,1);
     }
-    return [];
+    _numbersInputRef=numbers;
+    _numbersCache=random;
+    return random;
 }
 export const getBonusStatus=(state)=>{
     return state.turnplate.status.TURNPLATE_BONUS;

+ 6 - 6
src/layout/BreadCrumb/index.jsx

@@ -1,5 +1,5 @@
 import styles from './styles.module.scss';
-import {useEffect} from "react";
+import {Fragment, useEffect} from "react";
 import {NavLink, useLocation} from "react-router-dom";
 import {useSelector} from "react-redux";
 import {getRoute, getRouteChain} from "@features/mainSlice";
@@ -27,18 +27,18 @@ const BreadCrumb=({customChain=null})=>{
                         chain.map((item,index)=>{
                             let end=index===len-1;
                             return (
-                                <>
-                                    <NavLink key={index} to={`${!end?item.path:''}`}  className={`${!end?styles.nav_hover:styles.nav_active}`}>
+                                <Fragment key={index}>
+                                    <NavLink to={`${!end?item.path:''}`}  className={`${!end?styles.nav_hover:styles.nav_active}`}>
                                         <span>{i18n.t(item.title)}</span>
                                     </NavLink>
                                     {
                                         !end?(
-                                            <svg className={styles.icon} key={"arrow_"+index}>
+                                            <svg className={styles.icon}>
                                                 <use xlinkHref={`${symbol}#icon_Arrow`} />
                                             </svg>
-                                        ):(<></>)
+                                        ):null
                                     }
-                                </>
+                                </Fragment>
                             )
                         })
                     }

+ 17 - 25
src/layout/Routes/index.jsx

@@ -1,6 +1,6 @@
 import AllComponents, {Header} from '@pages/index';
 import {Route, Routes, useNavigate} from 'react-router-dom';
-import React, {cloneElement, lazy, Suspense} from "react";
+import React, {cloneElement, Fragment, lazy, Suspense} from "react";
 import SmallLoading from "@components/SmallLoading";
 import TransitionGroup from "react-transition-group/TransitionGroup";
 import CSSTransition from "react-transition-group/CSSTransition";
@@ -27,16 +27,12 @@ const CreateRoute=(props)=>{
         )
     }
     return (
-        <>
-            <Route
-                key={route.path}
-                exact
-                path={topath}
-                element={checkLogin()}
-            >
-
-            </Route>
-        </>
+        <Route
+            key={route.path}
+            exact
+            path={topath}
+            element={checkLogin()}
+        />
     )
 }
 
@@ -44,10 +40,10 @@ const CBrowserRouter=(props)=>{
     const {routes,isLogin}=props;
     return (
         <Routes>
-            <Route path="*" element={<PageNotFound/>}/>
+            <Route key="__notfound" path="*" element={<PageNotFound/>}/>
             {
                 routes.map((route,index)=>{
-                    return CreateRoute({...props,route,path:route.path,isLogin:isLogin});
+                    return CreateRoute({...props,route,path:route.path,isLogin:isLogin,key:route.path||index});
                 })
             }
         </Routes>
@@ -93,42 +89,38 @@ const CHashRouter=(props)=>{
             }}>
             {
                 hashs.map((item,index)=>{
-                    if (item=="")return (<></>);
+                    if (item=="")return (<Fragment key={`empty_${index}`}/>);
                     let hash="#"+item;
                     let route=getRoutes(hash);
-                    if (route==null)return (<></>);
+                    if (route==null)return (<Fragment key={`noroute_${index}`}/>);
                     if (!isLogin&&route.login==1){
                         //检测未登录
                         global.authLockPath=currpath;
                         navigate(pathname+currhash+route.lpath,{replace:true});
-                        return (<></>);
-                        // return (<Navigate to={pathname + currhash + route.lpath} replace={true}/>)
+                        return (<Fragment key={`nologin_${index}`}/>);
                     }
                     //再次检查路由
                     if (!checkRoute(route.path)){
                         navigate(pathname+currhash,{replace:true});
-                        return (<></>);
-                        // return (<Navigate to={pathname+currhash} replace={true}/>)
+                        return (<Fragment key={`badpath_${index}`}/>);
                     }
                     currhash+=hash;
                     if (route.type===ROUTE_TYPE_POP_OR_FULL)subIndex++;
                     return (
-                        // <CSSTransition timeout={timeout}>
-                            <RouteContainer level={subIndex} route={route} onClose={handleClose} header={Header[route.component]}>
+                            <RouteContainer key={`rc_${index}`} level={subIndex} route={route} onClose={handleClose} header={Header[route.component]}>
                                 <Suspense fallback={<SmallLoading/>}>
                                     <Routes key={index} location={{pathname:currpath,hash:hash,search}}>
                                         {
-                                            routes.map((route)=>{
+                                            routes.map((route,ri)=>{
                                                 if (route.path===hash){
-                                                    return CreateRoute({...props,route,path:currpath,close:handleClose,isLogin:isLogin});
+                                                    return CreateRoute({...props,route,path:currpath,close:handleClose,isLogin:isLogin,key:route.path||ri});
                                                 }
-                                                else return (<></>);
+                                                else return (<Fragment key={`skip_${ri}`}/>);
                                             })
                                         }
                                     </Routes>
                                 </Suspense>
                             </RouteContainer>
-                        // </CSSTransition>
                     )
                 })
             }

+ 8 - 8
src/layout/Sidebar/index.jsx

@@ -23,7 +23,7 @@ import {NavLink, useLocation,useNavigate} from 'react-router-dom';
 // hooks
 import {useSidebar} from '@contexts/sidebarContext';
 import {useWindowSize} from 'react-use';
-import {useEffect, useState} from 'react';
+import {Fragment, useEffect, useState} from 'react';
 
 // constants
 import LINKS from '@constants/links';
@@ -309,10 +309,10 @@ const Sidebar = () => {
         }
         return linkItem;
     }
-    const renderBlock=(block)=>{
-        if (block==null)return (<></>);
+    const renderBlock=(block,bkey)=>{
+        if (block==null)return (<Fragment key={`b_empty_${bkey}`}/>);
         let first=block[0];
-        if (first==null)return (<></>);
+        if (first==null)return (<Fragment key={`b_first_${bkey}`}/>);
         let blockID=first.block;
         let column=1;
         if (blocksColumn!=null){
@@ -320,16 +320,16 @@ const Sidebar = () => {
             if (blockC!=null)column=blockC.column;
         }
         return (
-            <>
+            <Fragment key={`b_${blockID||bkey}`}>
                 <StyledBlock open={open} column={column}>
                     {
                         block.map((link, index) => {
-                            return renderLinkNav(link)
+                            return (<Fragment key={link.id||link.path||index}>{renderLinkNav(link)}</Fragment>)
                         })
                     }
                 </StyledBlock>
                 {renderLine()}
-            </>
+            </Fragment>
         )
     }
     const renderLinkBlocks=()=>{
@@ -337,7 +337,7 @@ const Sidebar = () => {
             <>
                 {
                     navBlocks.map((block,index)=>{
-                        return renderBlock(block);
+                        return renderBlock(block,index);
                     })
                 }
             </>

+ 1 - 1
src/widgets/ModuleGroup/index.jsx

@@ -31,7 +31,7 @@ const ModuleGroup=({pageID})=>{
                             {
                                 modules.map((item,index)=>{
                                     let Comp=AllWidgets[item.type];
-                                    if (Comp==null)return (<></>);
+                                    if (Comp==null)return (<Fragment key={`m_skip_${index}`}/>);
                                     return (
                                         <Fragment key={index}>
                                             <Comp data={item}></Comp>

+ 1 - 9
src/widgets/WLangSelect/index.jsx

@@ -50,15 +50,7 @@ const WLangSelect=()=>{
         return (
             <div className={styles.content}>
                 {
-                    langs.map((item,index)=>{
-                        return (
-                            <>
-                                {
-                                    renderItem(item,currlang)
-                                }
-                            </>
-                        )
-                    })
+                    langs.map((item,index)=>renderItem(item,currlang))
                 }
             </div>
         )