I am a newbie trying to mess around React, I cam across a problem on which I have been stuck for like 2 days is that I have an Array (state array to be precise) in which I add values by SetArray method, all works fine and nice, however I am also assigning that Array values to another array and mapping the second array. Now the problem is the first array gets updated everywhere the second in which I assign values from first one doesn't render immediately, it renders only when the whole section gets rendered.
Setting Values in Array 1 on Click (is has complicated OnClick function as well, haven't added here, this works fine btw)
const [globalFLZ, setGlobalFLZ] = useState([]);
const addGlobalFLZ = (obj) => {
const idd = 1;
const newGlobalFLZ = { idd, ...obj };
setGlobalFLZ([...globalFLZ, newGlobalFLZ]);
}
Assigning values from Array 1 in Array 2
const weekColumns = {
[uuid()]: {
name: "All Items",
items: globalFLZ // assigning here
},
[uuid()]: {
name: "Week 1",
items: []
},
[uuid()]: {
name: "Week 2",
items: []
},
[uuid()]: {
name: "Week 3",
items: []
},
[uuid()]: {
name: "Week 4",
items: []
},
[uuid()]: {
name: "Week 6",
items: []
}
};
Code to Map Array 2
As this is nested array, first columns get mapped then items inside it
{Object.entries(columns).map(([columnId, column], index) => {
return (
<Box
boxShadow={1}
key={columnId}
className="diDragableColumn"
>
<Box className="diDragableColumnTitle" boxShadow={1}><h3>{column.name}</h3></Box>
<Droppable droppableId={columnId} key={columnId} direction="vertical">
{(provided, snapshot) => {
return (
<div
{...provided.droppableProps}
ref={provided.innerRef}
style={{
background: snapshot.isDraggingOver
? "lightgrey"
: "",
minHeight: '100%',
}}
className="diDropable"
>
{column.items.map((item, index) => { // the problem is here
return (
<Draggable
key={item.id}
draggableId={`dragID`+item.id}
index={index}
>
{(provided, snapshot) => {
return (
<Tooltip
title={item.answerAusformuliert}
arrow
placement="top"
className="di-tooltip"
classes={{
tooltip: classes.tooltip,
arrow: classes.arrow
}}
>
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={{
margin: "0 7px 7px 0",
...provided.draggableProps.style
}}
className="diDraggableItem"
>
{item.answerAusformuliert}
{item.id}
</div>
</Tooltip>
);
}}
</Draggable>
);
})}
{provided.placeholder}
</div>
);
}}
</Droppable>
</Box>
);
})}
Required: column.items.map should automatically re-map as Array 1 gets updated.
Sorry for the long and messy question but I am stuck bad any help would be greatly appreciated.
Thanks in advance.
fyi: I am using react-beautiful-dnd
EDIT Please check here: https://codesandbox.io/s/silent-haze-wvrv7
The problem is in your DragDrop component. Your columns
state isn't updated when new sendGlobalFLZ
is sent via props. This is because the useState
only runs once for initializing the value and then only updates the value when set[StateVar]
is used.
You can fix this by implemented useEffect
and providing sendGlobalFLZ
as a dependency. This will cause it to re-run and update your columns everytime it receives a new memory address for sendGlobalFLZ
.
const [allItemsUUID] = useState(() => uuid());
const [columns, setColumns] = useState(() => ({
[allItemsUUID]: {
name: "All Items",
items: sendGlobalFLZ
// items: staticData
},
[uuid()]: {
name: "Week 1",
items: []
},
[uuid()]: {
name: "Week 2",
items: []
},
[uuid()]: {
name: "Week 3",
items: []
},
[uuid()]: {
name: "Week 4",
items: []
},
[uuid()]: {
name: "Week 5",
items: []
}
}));
useEffect(() => {
const updatedColumns = {
...columns,
[allItemsUUID]: {
...columns[allItemsUUID],
items: sendGlobalFLZ
}
};
setColumns(updatedColumns);
}, [sendGlobalFLZ]);