Here is my code :
import React, { useState, useEffect } from 'react';
import { useCountriesQuery } from '../store/apis/userApi';
const CountryCmp = () => {
const {data} = useCountriesQuery('FR')
const [countryArray, setCountryArray] = useState(null)
useEffect(() => {
if(data){
setCountryArray(data.countries) // data.countries = [ { "selected": false, "value": "Afghanistan" }, { "selected": false, "value": "Afrique du Sud" }... { "selected": false, "value": "Allemagne" }, { "selected": True, "value": "France" }]
}
}, [data])
const [selectedCountry, setSelectedCountry] = useState('France')
const updateSelectedCountry = (value) => {
setSelectedCountry(value)
let clonedCountryArray = [...countryArray]
clonedCountryArray.map(item => {
if(item.selected === true){
item.selected = false
}
return item
})
clonedCountryArray.map(item => {
if(item.value === value){
item.selected = true
}
return item
})
console.log('countries', clonedCountryArray)
setCountryArray(clonedCountryArray)
}
return <>
{countryArray && <div className="pp-cons" >
<div className="col_form_full" >
<div>
<span data-ppui="true">{selectedCountry}</span>
<div>
<ul >
{countryArray.map((item,id) => {
return <li onClick={() => updateSelectedCountry(item.value)} key={id} >
<p >
<span className={"pp-"+(item.selected ? '_strong' : '')} > {item.value} </span>
</p>
</li>})}
</ul>
</div>
</div>
</div>
</div>}
</>
}
export default CountryCmp;
Here data are fetched correctly from REST API through RTK Query (useCountriesQuery).
When I click to invoke updateSelectedCountry, I got this error :
Cannot assign to read only property 'selected' of object '#<Object>'
TypeError: Cannot assign to read only property 'selected' of object '#<Object>'
I thought countryArray was the problem, so I cloned it to not avail.
I don’t understand why. Please help!
>Solution :
The map function creates a new array, but the objects inside it are still references to the original objects. Since you are modifying the objects within the cloned array directly, it can lead to issues.
You can create a deep copy of the countryArray to ensure that the objects inside are also cloned. You can use libraries like lodash for deep cloning or use a custom deep clone function.
const updateSelectedCountry = (value) => {
setSelectedCountry(value);
let clonedCountryArray = [...countryArray];
clonedCountryArray = clonedCountryArray.map((item) => ({ ...item }));
clonedCountryArray.forEach((item) => {
item.selected = item.value === value;
});
console.log('countries', clonedCountryArray);
setCountryArray(clonedCountryArray);
};