我有一个反应网格布局和使用redux来管理我的网格元素的状态。我可以用我想要的内容添加网格项,它们可以在网格中移动,并按我想要的方式调整大小。问题是,当我更改网格大小或位置时,它不会更新redux存储中的状态,因此当我离开仪表板页面并返回它时,网格对象将重置为其初始状态。我想使用一个动作来updateLayout,并试图在以下庄园这样做,虽然当我尝试和控制台日志我的布局我看到它没有更新。
这是我的减速器,包括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);
这是其中一个代码,我看得越多,我看到的东西越多,我们可以改进!因此,我可以帮助您处理未保存的redux状态,但我也有很多其他建议。
减速器误差
你们对UPDATE_LAYOUT
的减速机是完全错误的。您正在定义一个function
updateLayout
,它接受key
和value
并返回一个状态。而不是用action
的键和值来调用这个函数,你完全忽略了这个动作,而是在你的状态中添加一个包含这个函数的属性updateLayout
。
case actionTypes.UPDATE_LAYOUT:
return {
...state,
[action.key]: action.value
}
这应该修复减速机的情况。我们用...state
复制所有现有的状态属性,并添加/覆盖一个属性,其名称是来自您的操作的key
,其值是来自该操作的value
。
改进动作
为什么我们在action
中传递key
,而密钥总是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()
或layout.map()
)上调用内置数组映射方法相同。lodash方法允许您使用某些快捷方式选项,但您没有使用这些选项,因此没有任何优势。
你不需要state.count
数组,所以你应该从你的状态和你的reducer中删除它。
HTML/JSX改进从React Grid Layout文档中,似乎您需要将layout
对象作为道具传递给GridLayout
或在div
s上设置属性data-grid
,但您不需要同时做这两件事。所以你可以去掉一个。我将删除data-grid
.
你不应该在多个HTML元素上使用相同的id
属性,所以你不希望在一个循环中使用<div id = 'gridID'>
。
将相同的ref
传递给数组中的每个元素是没有意义的。这行不通。我不确定你想要实现的refs,因为你从来没有真正使用ref在任何地方,所以只是删除它。
span
元素呈现在同一行,但divs
是他们自己的块。而不是使用span
和br
,你可以只使用div
。
我不认为你需要DashItem
上的key
,除非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>
))}