为什么状态变量没有更新?

时间:2021-04-07 10:03:37

标签: javascript reactjs

我有一个 QQTable 函数组件,其中包含 1 个 QQTableBody。 而 QQTableBody 函数组件包含多个 QQRow 函数组件。 每个 QQRow 功能组件都有多个 QQCell 功能组件。

这是 QQTable 代码片段:

import {useCallback,useContext,useEffect, useState} from 'react';
import QQTableBody from './QQTableBody';
import QQTableHeader from './QQTableHeader';
import Roster from '../../utils/Roster';
import RosterWebContext from '../../utils/RosterWebContext';
import SelectedRegion from '../../utils/SelectedRegion';
import SelectedRegionUtil from '../../utils/SelectedRegionUtil';

export default function QQTable(props){
    const[activeShiftInfoList,setActiveShiftInfoList]=useState();
    const [rosterData,setRosterData]=useState();
    const [selectedRegion,setSelectedRegion]=useState(new SelectedRegion());
    let componentList=[];
    let systemParam=props.systemParam;

    let mouseUp=useCallback(()=>{
        console.log("mouse up");
        console.log(selectedRegion.inSelectMode);
        SelectedRegionUtil.endSelect(selectedRegion,setSelectedRegion);       
    },[selectedRegion]);
    
    useEffect(()=>{
        const getData = async () => {
            console.log("getData() is triggered");
            .................................
            let roster = new Roster();
            temp = await roster.getAllActiveShiftInfo();
            setActiveShiftInfoList(temp);
            temp= await roster.get(props.rosterMonth.getFullYear(),props.rosterMonth.getMonth()+1);
            setRosterData (temp); 

            document.addEventListener('mouseup',mouseUp);
            return () => {
                document.removeEventListener('mouseup', mouseUp)
            }
        }
        getData();    
    },[props.rosterMonth]);
    let contextValue={}
    if (rosterData){
        contextValue={
            activeShiftInfoList,
            rosterData,
            selectedRegion,
            setHightLightCellIndex,
            setRosterData,
            setSelectedRegion,
        }
        ..........
        componentList.push(<QQTableBody key="body"/>);
    }
    return(
            <RosterWebContext.Provider value={contextValue}>
                <table id="rosterTable">
                    {componentList}
                </table>
            </RosterWebContext.Provider>
    )
}

这是 QQCell 片段:

import {useContext} from 'react';
import RosterWebContext from '../../utils/RosterWebContext';
import SelectedRegionUtil from '../../utils/SelectedRegionUtil';
export default function QQCell(props){
    let cssClassName="QQ";
    let {
        selectedRegion,
        setSelectedRegion
    } = useContext(RosterWebContext);
    function mouseDownHandler(e){
        SelectedRegionUtil.startSelect(e.target,selectedRegion,setSelectedRegion);
    }
    function mouseEnterHandler(e){
        props.onMouseEnter(e);
        SelectedRegionUtil.updateSelect(e.target, selectedRegion,setSelectedRegion);
    }
    return (
        <td 
            className={cssClassName}
            contentEditable={true}           
            onMouseDown={mouseDownHandler}
            onMouseEnter={mouseEnterHandler}
            suppressContentEditableWarning={true}>
                {props.children}
        </td>
    )
}

还有 SelectedRegionUtil 的片段:

export default class SelectedRegionUtil{
    
    .....................
    
    static endSelect(selectedRegion,setSelectedRegion){
        if (selectedRegion.inSelectMode){
          let temp=JSON.parse(JSON.stringify(selectedRegion));
          temp.inSelectMode=false;
          setSelectedRegion(temp);
        }
    }

    ............................................
    
   static startSelect(theCell,selectedRegion,setSelectedRegion){
    let row=theCell.parentElement;
    let temp=JSON.parse(JSON.stringify(selectedRegion));
    temp.firstX=theCell.cellIndex;
    temp.firstY=row.rowIndex;
    temp.minX=theCell.cellIndex;
    temp.minY=row.rowIndex;
    temp.maxX=theCell.cellIndex;
    temp.maxY=row.rowIndex;
    temp.inSelectMode=true;
    console.log("temp="+JSON.stringify(temp));
    setSelectedRegion(temp);
  }
  
  ..........................................................
  
  static updateSelect(theCell,selectedRegion,setSelectedRegion){
    if (selectedRegion.inSelectMode){
      let cellIndex=theCell.cellIndex;
            let isChanged=false;
            let newMaxX=selectedRegion.maxX,newMinX=selectedRegion.minX;
            let newMaxY=selectedRegion.maxY,newMinY=selectedRegion.minY;
            let row=theCell.parentElement;
            let rowIndex=row.rowIndex;

      if (cellIndex<selectedRegion.firstX)
            {
                newMinX=cellIndex;
                isChanged=true;
            }
            else
            {
                if (cellIndex>selectedRegion.firstX)
                {
                    newMaxX=cellIndex;
                    isChanged=true;
                }
                else
                {
                    newMinX=selectedRegion.firstX;
                    newMaxX=selectedRegion.firstX;
                    isChanged=true;
                }   
            }
            if (rowIndex>selectedRegion.firstY)
            {
                newMaxY=rowIndex;
                isChanged=true;
            }
            else
            {
                if (rowIndex<selectedRegion.firstY)
                {
                    newMinY=rowIndex;
                    isChanged=true;
                }
                else
                {
                    newMinY=selectedRegion.firstY;
                    newMaxY=selectedRegion.firstY;
                    isChanged=true;
                }   
            }
      if (isChanged){
        //console.log("isChanged=true");
        let temp=JSON.parse(JSON.stringify(selectedRegion))
        temp.minX=newMinX;
                temp.maxX=newMaxX;
                
                temp.minY=newMinY;
              temp.maxY=newMaxY;
        setSelectedRegion(temp);
      }
    }
  }   
}

最后,SelectedRegion 片段:

export default class SelectedRegion{
    constructor(){
        this.firstX=-1;
        this.firstY=-1;
        this.inSelectMode=false;
        this.minX=-1;
        this.minY=-1;
        this.maxX=-1;
        this.maxY=-1;
    }
}

上面的代码片段显示了 QQCell 功能组件调用 SelectedRegionUtil 将状态变量 selectedRegion.inSelectMode 更改为 true。

不幸的是,QQTable 中的 mouseUp 函数总是显示 selectedRegion.inSelectMode 的值为 false。

我曾尝试将 mouseUp 函数移动到 useEffect 函数中,但结果是一样的。

你会如何解决它?

或者有什么包可以只在表的一个区域而不是整个表中执行选择、复制和粘贴功能?

1 个答案:

答案 0 :(得分:0)

最后,在 QQTable 组件中,我从 useEffect 钩子中删除了以下代码:

document.addEventListener('mouseup',mouseUp);
return () => {
    document.removeEventListener('mouseup', mouseUp)
}

然后在 useEffect 组件中添加另一个 QQTable 钩子:

useEffect(()=>{
    document.addEventListener('mouseup',mouseUp);
    return () => {
        document.removeEventListener('mouseup', mouseUp)
    }
},[mouseUp])

它按我的预期工作。