import { useState } from "react";
function App() {
const [itemsClicked, setItemsClicked] = useState([]);
const dataList = [
{ id: 1, name: "jake" },
{ id: 12, name: "edd" },
{ id: 13, name: "john" }
];
const highlight = (data) => {
setItemsClicked((array) => {
let itemClicked = array.includes(data)
? array.filter((x, i) => x.id !== data.id)
: [...array, data]; // What I'm trying to do here is to add a new field which is 'active' >> [...array, {...data, active: true}];
return itemClicked;
});
};
return (
<div>
{dataList.map((item, i) => (
<div
style={{
borderColor: itemsClicked[i]?.active ? "1px solid green" : ""
}}
>
<button onClick={() => highlight(dataList[i])}>HIGHLIGHT</button>
</div>
))}
</div>
);
}
export default App;
What I'm trying to do here is to create a toggle which is to highlight the div
.
but my problem is on the state instead of it will remove the data object, it will continue appending. how to fix it?
for example when I try to click the first data which is jake
, the output should be like this in itemsClicke
[{ id: 1, name: jake, active: true }]
but when I try to click again it will just remove it from the list, but on my side, it continuing to append the data which is wrong
[{ id: 1, name: jake, active: true },{ id: 1, name: jake, active: true },{ id: 1, name: jake, active: true },{ id: 1, name: jake, active: true }]
CodePudding user response:
Just use this. It's a simple example. I used itemsClicked only for storing the ids
const highlight = (data) => {
if(itemsClicked.indexOf(data.id) == -1)
{
setItemsClicked(prevData => {
return [...prevData, data.id]
})
}
}
{
dataList.map((item, i) => (
<div
style={{
border:
itemsClicked.indexOf(item.id) > -1 ? '1px solid green' : '',
}}
>
{itemsClicked.indexOf(item.id) > -1 ? '1px solid green' : ''}
<button onClick={() => highlight(dataList[i])}>HIGHLIGHT</button>
</div>
))
}
CodePudding user response:
You can simply remove the itemsClicked
state and put the dataList
in a state variable to have control over it:
const [dataList, setDataList] = useState([
{ id: 1, name: "jake" },
{ id: 12, name: "edd" },
{ id: 13, name: "john" }
]);
Now, you need to check an isActive
property to conditionally add some styles, so you need isActive
but it's not in the current dataList
and you created itemsClicked
to solve this issue. But there are some simpler solutions like adding a property on the fly with your dataList
.
You can implement toggleHighlight
function to change isActive
property:
const toggleHighlight = (id) => {
setDataList((prevState) =>
prevState.map((item) =>
item.id === id ? { ...item, isActive: !item.isActive } : item
)
);
};
this toggleHandler
will accept an id and take a for loop over the dataList
, it finds the clicked item. if it's an active item so it changes it to false and vice versa.
let's recap and put all things together:
import { useState } from "react";
function App() {
const [dataList, setDataList] = useState([
{ id: 1, name: "jake" },
{ id: 12, name: "edd" },
{ id: 13, name: "john" }
]);
const toggleHighlight = (id) => {
setDataList((prevState) =>
prevState.map((item) =>
item.id === id ? { ...item, isActive: !item.isActive } : item
)
);
};
return (
<div>
{dataList.map((item) => (
<div
key={item.id}
style={{
display: "flex",
paddingTop: 10,
border: item.isActive ? "2px solid green" : ""
}}
>
<p style={{ padding: 5 }}>{item.name}</p>
<button onClick={() => toggleHighlight(item.id)}>HIGHLIGHT</button>
</div>
))}
</div>
);
}
export default App;
CodePudding user response:
array.includes(data)
won't return true because of this: https://stackoverflow.com/a/50371323/17357155