I'm making checkbox function using data in json file.
I want to show 'O' and 'X' according to the value called checked
in json file.
And want checked
value changed when 'O' or 'X' is clicked.
For this, I tried to make handleCheck
function but it doesn't work.
May I know which part is wrong and how to modify it?
App.js
import "./styles.css";
import dummy from "./database/data.json";
export default function App() {
const handleCheck = (number) => {
dummy.state[number].checked !== dummy.state[number].checked;
};
return (
<div className="App">
{dummy.state.map((item, idx) => {
return (
<div
onClick={() => {
handleCheck(item.id);
}}
key={idx}
>
{item.checked ? "O" : "X"}
</div>
);
})}
</div>
);
}
data.json
{
"state": [
{
"id": "1",
"checked": true
},
{
"id": "2",
"checked": true
},
{
"id": "3",
"checked": true
}
]
}
codesandbox
https://codesandbox.io/s/serene-forest-j0cb25?file=/src/database/data.json:0-176
CodePudding user response:
First you need to move the json data to a state value and update the state value accordingly and at the end you can push the json data out
import "./styles.css";
import dummy from "./database/data.json";
export default function App() {
const [data,setData]=useState(dummy.state)
const handleCheck = (number) => {
setData(state=>{
let newState=[...state]
newState[number].checked = !state[number].checked;
return newState
}
};
return (
<div className="App">
{data.map((item, idx) => {
return (
<div
onClick={() => {
handleCheck(item.id);
}}
key={idx}
>
{item.checked ? "O" : "X"}
</div>
);
})}
</div>
);
}
The data state value have the correct values and you can use them accordingly
CodePudding user response:
You're running into some JavaScript syntax issues and React-specific issues.
One of them is that you're modifying the JSON file array directly, and React isn't going to re-render on those changes. A way to fix this would be to use the useState
hook with your dummy data as the initial state. You can accomplish this like so:
const [data, setData] = useState(dummy.state)
Now, we have a data
variable which corresponds to your dummy data's state array and a setData
function which will let us set data
to whatever value we'd like and have React re-render the UI.
The next bit we need to tackle will be to make sure the handleCheck
function is updating our useState
's data
variable and setting it correctly. We have two big issues right now with this function.
First, you're really close to flipping the checked
value, but the o.checked !== o.checked
is doing a comparison instead of setting your variable; basically, the code is asking "is X strictly not equal to X?" MDN has a great page on what strict inequality is. What we'd like to do is set A.checked to "not A.checked". To fix this, we can do item.checked = !item.checked
.
Additionally, calling dummy.state[number].checked
doesn't point to what you probably think it will since your IDs are keys on an object. If number = 1
, then dummy.state[1]
actually ends up being the second item in the array, because JavaScript arrays are 0-indexed. Instead, we can update the function like so
const handleCheck = (id) => {
setData(
data.map((item) => {
return item.id === id
? { ...item, checked: !item.checked }
: { ...item };
})
);
};
Now what we're doing is using the map
function to loop over your data
, destructure it (arrays are references, and we don't want to mutate the "old" data), and conditionally change the checked
property based on if the item's ID matches the ID passed into handleChecked
.
I've forked and updated your CodeSandbox so you can see it all put together in App.js
.