0

我正在设计一个仪表板 UI,用户可以在其中使用 react-grid-layout 创建具有不同可视化效果的自定义仪表板。我有它,所以当用户更改布局时,它会保存到本地存储中。当页面被刷新时,布局被返回。这目前正在工作,除了高度。当用户刷新页面时,网格项目的宽度和位置会恢复,但是它们都以行高 1 呈现,直到项目被移动,然后所有高度都恢复为它们存储的值。我可以看到高度的本地存储值都是正确的,所以我不确定为什么刷新时高度不正确。

这是我正在使用的代码:

const Dash = () => {
  //hook to determine when drag background shows
  const [isDragging, setIsDragging] = React.useState(false)

  //Variable used for id of grid component:
  const id = uuid()

  // Hook to set layout state
  const savedLayout = getLayout(username+1)  
 

  //column size is static
  //layouts taken from local storage via function
  const [ state, setState ] = React.useState({
    cols: { lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 },
    rowHeight: 30,
    layout: savedLayout
  })

  //function ammends layout array with additional grid item
  const addItem = () => { 
    console.log('adding: ' + id);
    const newLayout = state.layout;
    newLayout.push({
      i: `${id}`,
      x: 0,
      y: 0,
      w: 3,
      h: 3
    })
    setState({layout: newLayout})
  }

  //function to remove grid item on click
  const removeItem = (i) => {
    console.log(i)
    setState({ layout: _.reject(state.layout, { i:i }) })     
  }

   //function to calculate where to add items based on the cols
   const onBreakpointChange = (breakpoint, cols) => {
    setState({
      cols: cols,
      breakpoint: breakpoint
    })
    console.log(state)
  }

  //function to save layout to LS everytime a grid item is moved.
  const onLayoutChange = () => {
    saveLayout(username+1, state.layout)
    console.log(state.layout)
  }

  //When item is dropped, the dragbackground will disappear and
  //Layout state is updated
  const onMoveStop = (layout) => {
    setIsDragging(false);
    setState({ layout: layout })
  }



  return (
    <div>
      <button onClick={addItem}>Add Item</button>
      <Dragfield
        {...state}
        className="layout"
        onDragStart={() => setIsDragging(true)}
        onDragStop={(layouts) => onMoveStop(layouts)}
        onResizeStart={() => setIsDragging(true)}
        onResizeStop={(layouts) => onMoveStop(layouts)}
        isDragging={isDragging}
        breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
        onBreakpointChange={onBreakpointChange}
        onLayoutChange={() => onLayoutChange()}
        cols={{ lg: 12, md: 12, sm: 6, xs: 4, xxs: 2 }}
        resizeHandles={['se']}
        compactType={'vertical'}
        draggableHandle=".dragHandle"               
     >        
        {_.map(state.layout, (item, i) => (
          <div key={item.i} data-grid={state.layout[i]}>            
          <DashItem key={item.i}>
            <button onClick={() => removeItem(item.i)}>Remove Item</button>  
            <CreateGraph data={state.layout[i]}/>
          </DashItem>
          <div className='dragHandle'>Drag From Here</div>
          </div>
      ))}
      </Dragfield>
    </div>
  );
}

//function to get user layout from LS
const getLayout = (key) => {
    try {
        const serialisedState = localStorage.getItem(key);
        if (serialisedState === null) {
          return []
        }
        return JSON.parse(serialisedState);
    } catch (error) {
      return []
    }
}

//function to save user layout to LS
const saveLayout = ( layoutName, state) => {
    try {
        const serialisedState = JSON.stringify(state);
        localStorage.setItem(layoutName, serialisedState);
    } catch (error) {
        console.log("local storage error")
    }
}

export default Dash;

4

1 回答 1

1

您应该为cols,rowHeight和使用单独的状态layout

当你打电话时

setState({
  cols: cols,
  breakpoint: breakpoint
})

您间接设置layoutundefined.

你应该这样做:

const [cols, setCols] = useState({ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 });
const [rowHeight, setRowHeight] = useState(30);
const [layout, setLayout] = useState(getLayout(username + 1));

或者,如果您不想使用单独的状态,您可以执行以下操作:

setState(prevState => ({
  ...prevState,
  cols: cols,
  breakpoint: breakpoint
}))
于 2021-03-05T11:18:15.257 回答