1

我在让我的 react-grid-layout 在加载时从本地存储读取时遇到问题。我想保存它并使用特定于每个不同用户的用户名键访问布局。我可以将布局保存到本地存储中,并且这样做没有问题,并且可以看到当我更改布局时它们正在发生变化。当我重新加载页面时,但布局尚未保存,本地存储将清除,当我尝试添加新项目时,我收到一个错误,告诉我无法将新项目推送到我的对象数组(布局)。当我再次刷新页面时,此错误消失。我在下面的代码中显示了完整的错误。我希望能够尽可能地添加/删除我的布局,并且当该布局发生更改时,我想将其保存到本地存储中,以便在刷新页面或用户单击页面时,

const ReactGridLayout = WidthProvider(Responsive);

const Dragfield = styled(ReactGridLayout)`
margin: 10px 0px 0px 0px;
${props => props.isDragging ? `
  background: url(${dragBackground});
  background-repeat: repeat-y;
  background-position: 100% 0px;
  background-size: 100% 100px
`: ''};
`

//Find username form localstorage (uuid string)
const username = localStorage.getItem('username')

const Dash = (props) => {
  const [isDragging, setIsDragging] = React.useState(false);
  //Variable used for id of grid component:
  const id = uuid()

  //Hook to set layout state
  const originialLayouts = getLayout("layouts")  || [].map(function(i, list) {
    return {
      i: i.toString(),
      x: i * 2,
      y: 0,
      w: 3,
      h: 3,
      add: i === (list.length - 1)
    }
  });
 
  const savedLayout = JSON.parse(JSON.stringify(originialLayouts))
  console.log(JSON.parse(JSON.stringify(originialLayouts)))

  //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: (state.layout.length * 3) % (state.cols || 12),
      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 = (layout, layouts) => {
    console.log(layouts)
    saveLayout("layouts", state.layout)
    console.log(state.layout)
    setState({ layout: layout})
  }


  return (
    <div>
      <button onClick={addItem}>Add Item</button>
      <Dragfield
        {...state}
        className="layout"
        onDragStart={() => setIsDragging(true)}
        onDragStop={() => setIsDragging(false)}
        onResizeStart={() => setIsDragging(true)}
        onResizeStop={() => setIsDragging(false)}
        isDragging={isDragging}
        breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
        onBreakpointChange={onBreakpointChange}
        onLayoutChange={(layout, layouts) => onLayoutChange(layout, layouts)}
        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>
            <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) => {
  let ls = [];
  if (global.localStorage) {
    try {
      ls = JSON.parse(global.localStorage.getItem(username + 1)) ||
      [].map(function(i, list) {
        return {
          i: i.toString(),
          x: i * 2,
          y: 0,
          w: 3,
          h: 3,
          add: i === (list.length - 1)
        }
      });
    } catch (error) {
      console.log('error with getLayout')
    }
  }
  return ls[key]
}

//function to save user layout to LS
const saveLayout = ( key, value ) => {
  if (global.localStorage) {
    global.localStorage.setItem( username+1, JSON.stringify({ [key]: value}) );
  }
}

export default Dash;

编辑:

添加项目时显示的错误代码:

Uncaught TypeError: Cannot read property 'push' of undefined
    at addItem (static/js/main.chunk.js:1096)
    at HTMLUnknownElement.callCallback (static/js/1.chunk.js:794981)
    at Object.invokeGuardedCallbackDev (static/js/1.chunk.js:795030)
    at invokeGuardedCallback (static/js/1.chunk.js:795090)
    at invokeGuardedCallbackAndCatchFirstError (static/js/1.chunk.js:795105)
    at executeDispatch (static/js/1.chunk.js:799340)
    at processDispatchQueueItemsInOrder (static/js/1.chunk.js:799372)
    at processDispatchQueue (static/js/1.chunk.js:799385)
    at dispatchEventsForPlugins (static/js/1.chunk.js:799396)
    at static/js/1.chunk.js:799607
    at batchedEventUpdates$1 (static/js/1.chunk.js:813292)
    at batchedEventUpdates (static/js/1.chunk.js:794779)
    at dispatchEventForPluginEventSystem (static/js/1.chunk.js:799606)
    at attemptToDispatchEvent (static/js/1.chunk.js:797089)
    at dispatchEvent (static/js/1.chunk.js:797007)
    at unstable_runWithPriority (static/js/1.chunk.js:893924)
    at runWithPriority$1 (static/js/1.chunk.js:802387)
    at discreteUpdates$1 (static/js/1.chunk.js:813309)
    at discreteUpdates (static/js/1.chunk.js:794791)
    at dispatchDiscreteEvent (static/js/1.chunk.js:796973)

4

1 回答 1

0

存在错误是因为我使用 onLayoutChange 来更新我的布局。这意味着当我刷新我的网格时,布局在从本地存储中获取之前已更新,因此,当我从本地存储中调用时,它返回 undefined 导致错误。

我通过设置它来解决这个问题,以便 onLayoutChange 将布局保存到本地存储,但状态仅更新 onResizeStop 和 onDragStop。

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;
于 2021-03-05T10:50:58.247 回答