简体   繁体   中英

Why the state variable is not updated?

I have a QQTable functional component that contains 1 QQTableBody . And the QQTableBody functional component contains several QQRow functional components. And each QQRow functional components has several QQCell functional components.

Here is the QQTable snippnet:

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>
    )
}

Here is the QQCell snippet:

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>
    )
}

And the snippet of 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);
      }
    }
  }   
}

Finally, the SelectedRegion snippet:

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;
    }
}

The above snippet shows the QQCell functional component call SelectedRegionUtil to change the state variable selectedRegion.inSelectMode to true.

Unfortunately, the mouseUp function in QQTable always shows the value of selectedRegion.inSelectMode is false.

I have tried to move the mouseUp function into the useEffect function, but the result is the same.

Would you how to fix it?

Or is there any package that can perform the select, copy and paste function in a region of a table only but not the whole table?

Finally, in the QQTable component, I remove the following coding from useEffect hook:

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

And then add another useEffect hook in the QQTable component:

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

It works as I expected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM