0

我有一个反应网格布局,并且正在使用 redux 来管理我的网格元素的状态。我可以添加包含我想要的内容的网格项目,它们可以在网格周围移动并按照我想要的方式调整大小。问题是当我更改网格大小或位置时,它不会更新 redux 存储中的状态,因此当我离开仪表板页面并返回它时,网格对象会重置为其初始状态。我想使用一个动作来更新布局,并尝试在下面的庄园中这样做,尽管当我尝试控制台记录我的布局时,我发现它没有更新。

这是我的减速器,包括 addItem:

const initialState = {
    layout: [],
    count:[],
};


const reducer = (state=initialState, action) => {
    switch (action.type) {
        case actionTypes.ADD_GRID_ITEM:
            const id = uuid()
            console.log("adding: " + id)
            return{
                ...state,
                count: state.count.concat(<CreateGraph/>),
                layout: state.layout.concat({
                    i: `${id}`,
                    x: 2,
                    y: 0,
                    w: 4,
                    h: 5
                }),
            }

        case actionTypes.UPDATE_LAYOUT:            
            const updateLayout = (key, value) => {
                Object.assign(
                    {},
                    state,
                    {
                        [key]: value,
                    },
                );
            }
            return {
                ...state,
                updateLayout
                
            }
            

    }
    return state;
}

export default reducer;

这是我的反应网格布局的代码。我想在每次更改布局时更新布局 - 这可以使用 onLayoutChange 属性来完成。

const ReactGridLayout = WidthProvider(Responsive);

const Dash = (props) => {
  const layout = props.layout
  const { value, addItem, updateLayout } = props
  const ref = useRef()

  const onLayoutChange = (layout, layouts) => {
    props.updateLayout("layouts", layouts)
    console.log(...props.layout)
  }

  return (
    <div>
      <button onClick={addItem}>Add Item</button>
        <ReactGridLayout
          {...props}
          className="layout"
          layouts={props.layout}
          onLayoutChange={(layout, layouts => onLayoutChange(layout, layouts))}
          breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
          cols={{ lg: 12, md: 12, sm: 6, xs: 4, xxs: 2 }}
          resizeHandles={['s', 'w', 'e', 'n', 'sw', 'nw','se', 'ne']}
          verticalCompact={false}
          draggableHandle=".dragHandle"
               
      >        
        {_.map(value, (item, i) => (
          <div id = 'gridID' ref={ref} key={i} data-grid={props.layout[i]}>
            <span className='dragHandle'>Drag From Here</span>
            <br/>
            <DashItem  key={i} >
              {item}
            </DashItem>
            <span className='dragHandle'>Drag From Here</span>
          </div>
        ))}
        </ReactGridLayout>
    </div>
  );
}


Dash.propTypes = {
  value: PropTypes.array,
  onIncreaseClick: PropTypes.func.isRequired
}


const mapStateToProps = (state) => {
  return {
    value: state.count,
    layout: state.layout,
    onLayoutChange: state.onLayoutChange,
  };
};

const mapDispatchToProps = dispatch => { 
  return {
    addItem: () => dispatch({type: actionTypes.ADD_GRID_ITEM}),
    updateLayout: (key, value) => dispatch({type: actionTypes.UPDATE_LAYOUT, key, value})
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Dash);
4

1 回答 1

1

这是其中一种代码,我看的越多,我看到的可以改进的东西就越多!因此,我可以帮助您解决未保存的 redux 状态,但我还有很多其他建议。

减速机错误

你的减速机UPDATE_LAYOUT全错了。您正在定义 a function updateLayout,它接受一个key并且value返回一个状态。而不是使用您的键和值调用该函数action,您完全忽略该操作,而是updateLayout向您的状态添加一个包含此函数的属性。

case actionTypes.UPDATE_LAYOUT:            
    return {
        ...state,
        [action.key]: action.value
    }

这应该修复那个减速器的情况。我们复制所有现有的状态属性...state并添加/覆盖一个属性,该属性的名称是key来自您的操作,其值是value来自该操作。

改善行动

为什么我们keyactionkey is always 时传递 a layout?为什么不将布局存储在payload动作的属性中?(使用属性名称payload不是必需的,但这是标准约定)。

const mapDispatchToProps = dispatch => { 
  return {
    addItem: () => dispatch({type: actionTypes.ADD_GRID_ITEM}),
    updateLayout: (layout) => dispatch({type: actionTypes.UPDATE_LAYOUT, payload: layout})
  }
}
case actionTypes.UPDATE_LAYOUT:            
    return {
        ...state,
        layout: action.payload
    }

状态中的组件

state.count似乎是一个<CreateGraph/>元素数组。虽然不是致命错误,但这不是一个好主意。一般来说,我建议将组件的 props 存储在 redux 状态而不是组件本身。但在这种情况下,您的组件没有道具!那么为什么我们需要存储它呢?

在我看来,它存在的唯一原因是你有一个与数组长度相同的layout数组。这不是必需的。您可以遍历layout数组以获取索引并忽略值。但我实际上认为使用布局元素中的唯一 id 作为键而不是数组索引会更好。

注意:lodash_.map()很好,但在这种特殊情况下,它与仅在数组上调用内置数组映射方法(如value.map()or )相同。layout.map()lodash 方法允许您使用某些快捷方式选项,但您没有使用这些选项,因此没有任何优势。

您不需要该state.count数组,因此您应该将其从您的状态和减速器中删除。

HTML/JSX 改进

React Grid Layout docs看来,您似乎需要将layout对象作为道具传递给sGridLayout data-grid在s 上设置属性div,但您不需要两者都做。所以你可以删除一个。我会删除data-grid.

您不应id在多个 HTML 元素上使用相同的属性,因此您不希望在循环中使用此属性<div id = 'gridID'>

ref将相同的值传递给数组中的每个项目是没有意义的。这行不通。我不确定你想用 ref 实现什么,因为你从来没有在任何地方实际使用过 ref,所以只需删除它。

span元素呈现在同一行,但divs它们是自己的块。而不是使用 aspan和 abr你可以只使用 a div

我认为您不需要 a keyon the ,DashItem除非DashItem组件出于某种原因需要它。您只需要循环中最外层元素上的一个键,而您已经拥有该键。

{layout.map((item) => (
    <div key={item.i}>
        <div className='dragHandle'>Drag From Here</div>
        <DashItem>
            <CreateGraph />
        </DashItem>
        <div className='dragHandle'>Drag From Here</div>
    </div>
))}
于 2021-02-21T22:26:35.813 回答