whenever my layout changes, it will save the new changes into localstorage and update my layout state
onLayoutChange(layouts) {
saveToLS("layouts", layouts);
}
However, the issue occurs When the page is refreshed. layout was updated before it was fetched from local storage, this means it discard all the changes and reset the layout to default. The image below shows what i mean
What should I do to prevent this from happening?? I am following this guide. It is working on the guide but not for me, really appreciate any help
Here is the full code I am using
const originalLayouts = getFromLS("layouts") || {};
const ResponsiveReactGridLayout = WidthProvider(Responsive);
class MinMaxLayout extends React.PureComponent {
static defaultProps = {
margin:[0,0],
className:"layout",
cols: { lg: 1, md: 10 },
rowHeight: 100
};
constructor(props) {
super(props);
this.state = {
layouts: JSON.parse(JSON.stringify(originalLayouts)),
inputWidthVal: "",
inputHeightVal:"",
items: [0, 1, 2, 3, 4].map(function (i, key, list) {
return {
id: uuidV4(),
i: i.toString(),
x: i * 2,
y: 0,
w: 1,
h: 1
};
}),
charts: [0].map(function (i, key, list) {
return {
id: uuidV4(),
i: i.toString(),
x: i,
y: 0,
w: 4,
h: 3
};
}),
newCounter: 0,
chartCounter:0
};
this.onAddItem = this.onAddItem.bind(this);
this.onChartItem = this.onChartItem.bind(this);
this.onBreakpointChange = this.onBreakpointChange.bind(this);
}
createElement(el) {
const removeStyle = {
position: "absolute",
left: "11px",
top: 0,
cursor: "pointer"
};
const i = el.i;
return (
<div key={el.id} data-grid={el} >
<span
className="remove"
style={removeStyle}
onClick={this.onRemoveItem.bind(this, i)}
>
x
</span>
</div>
);
}
// this is the charts that was created when the DOM was render
createChart(el) {
const removeStyle = {
position: "absolute",
left: "11px",
top: 0,
cursor: "pointer"
};
const i = el.i;
return (
// <div key={el.id} data-grid={el} onClick={((e) => this.handleClick(e))}>
<div key={el.id} data-grid={el} className="graph">
<Newvsresturnvisitors />
<span
className="remove"
style={removeStyle}
onClick={this.onRemoveChartItem.bind(this, i)}
>
x
</span>
</div>
);
}
onAddItem() {
this.setState({
// Add a new item. It must have a unique key!
items: this.state.items.concat({
id: uuidV4(),
i: "n" + this.state.newCounter,
x: (this.state.items.length * 2) % (this.state.cols || 12),
y: Infinity, // puts it at the bottom
w: 1,
h: 1
}),
// Increment the counter to ensure key is always unique.
newCounter: this.state.newCounter + 1
});
}
onChartItem() {
this.setState({
// Add a new item. It must have a unique key!
charts: this.state.charts.concat({
id: uuidV4(),
i: "n" + this.state.chartCounter,
x: (this.state.charts.length * 2) % (this.state.cols || 12),
y: 0, // puts it at the bottom
w: 4,
h: 3
}),
// Increment the counter to ensure key is always unique.
chartCounter: this.state.chartCounter + 1
});
}
// We're using the cols coming back from this to calculate where to add new items.
onBreakpointChange(breakpoint, cols) {
this.setState({
breakpoint: breakpoint,
cols: cols
});
}
onRemoveItem(i) {
this.setState({ items: _.reject(this.state.items, { i: i }) });
}
clearAllItem = ()=>{
this.setState({ items: [], charts: [] });
}
onRemoveChartItem(i){
this.setState({ charts: _.reject(this.state.charts, { i: i }) });
}
inputCanvasDimension = e =>{
const re = /^[0-9\b]+$/;
if (e.target.value === '' || re.test(e.target.value)) {
if(e.currentTarget.className === "inputWidth"){
this.setState({inputWidthVal: e.currentTarget.value});
}else if(e.currentTarget.className === "inputHeight"){
this.setState({inputHeightVal: e.currentTarget.value});
}
}
}
setCanvasDimension = () =>{
var canvas = document.getElementById("DetailLocationContainer");
if((this.state.inputWidthVal < 1000) || (this.state.inputHeightVal < 3000)){
alert("Width should not be less than 1000 and height should not be less than 3000");
}else {
canvas.style.width= this.state.inputWidthVal + "px";
canvas.style.height= this.state.inputHeightVal + "px";
}
}
saveToLS(key, value) {
var secondObject = Object.entries(value)[1];
if (global.localStorage) {
global.localStorage.setItem(
"rgl-8",
JSON.stringify({
[key]: value
})
);
}
}
onLayoutChange(layout, layouts) {
this.saveToLS("layouts", layouts);
}
onDrop = (layout, layoutItem, _event) => {
if(_event.dataTransfer.mozSourceNode.className === "textwidget"){
this.setState({
items: this.state.items.concat({
id: uuidV4(),
i: "n" + this.state.newCounter,
x: layoutItem.x,
y: layoutItem.y,
w: 1,
h: 1
}),
newCounter: this.state.newCounter + 1
});
}else if(_event.dataTransfer.mozSourceNode.className === "chart"){
this.setState({
// Add a new item. It must have a unique key!
charts: this.state.charts.concat({
id: uuidV4(),
i: "n" + this.state.chartCounter,
x: (this.state.charts.length * 2) % (this.state.cols || 12),
y: Infinity, // puts it at the bottom
w: 5,
h: 6
}),
// Increment the counter to ensure key is always unique.
chartCounter: this.state.chartCounter + 1
});
}
};
reset = () =>{
// window.location.reload(true);
this.setState({ layouts: {} });
}
render() {
return (
<div className="container" id="container">
<div className="btn_container">
<div>
<span>Width </span>
<input className="inputWidth" value={this.state.inputWidthVal} onChange={this.inputCanvasDimension}/>
<span> Height </span>
<input className="inputHeight" value={this.state.inputHeightVal} onChange={this.inputCanvasDimension}/>
<button onClick={this.setCanvasDimension}>Apply</button>
<button onClick={this.reset}><CachedIcon style={{fontSize: '14px'}}/></button>
<button onClick={openFullscreen}><FullscreenSharpIcon style={{fontSize: '14px'}}/></button>
</div>
</div>
<button id="createItemBtn" onClick={this.onAddItem}>Add Item</button>
<button id="createChartBtn" onClick={this.onChartItem}>Add Chart</button>
<button onClick={this.clearAllItem}>Clear All</button>
<div className="widgetcontainer">
<WidgetThumbnail
className="chart"
/>
<WidgetThumbnail
className="textwidget"
/>
</div>
<div className='DetailLocationContainer' id="DetailLocationContainer" >
<ResponsiveReactGridLayout
cols={{ lg: 1, md: 10, sm: 6, xs: 4, xxs: 2 }}
rowHeight={100}
onDrop={this.onDrop}
isDroppable={true}
isBounded={true}
layouts={this.state.layouts}
onLayoutChange={(layout, layouts) =>
this.onLayoutChange(layout, layouts)
}
onBreakpointChange={this.onBreakpointChange}
{...this.props}
>
{_.map(this.state.items, (el) => this.createElement(el))}
{_.map(this.state.charts, (el) => this.createChart(el))}
</ResponsiveReactGridLayout>
</div>
</div>
);
}
}
export default MinMaxLayout;
const rootElement = document.getElementById("root");
ReactDOM.render(<MinMaxLayout />, rootElement);
This is my getFrinLS
export function getFromLS(key) {
let md = {};
if (global.localStorage) {
try {
md = JSON.parse(global.localStorage.getItem("rgl-8")) || {};
} catch (e) {
/*Ignore*/
}
// console.log("return value ", md[key]);
return md[key];
}
}
Looks like incremental keys are needed to apply updated layout. Change the key value from el.id to i
createElement(el) {
const removeStyle = {
position: "absolute",
left: "11px",
top: 0,
cursor: "pointer"
};
const i = el.i;
return (
<div key={i} data-grid={el} >
<span
className="remove"
style={removeStyle}
onClick={this.onRemoveItem.bind(this, i)}
>
x
</span>
</div>
);
}