Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Data object property is read only

I know that sometimes when the frontend receives data from mongoose, it is as a read-only document. However, when I go the error today: TypeError: "contracts" is read-only, my first thought was this and so I assigned a new variable to the data, tried running a map on the data (data.map(x => x)), tried assigning the data with a spread operator, but I keep getting the same error, so I really dont know what I’m missing.

Heres the data that comes in, as logged in the console:

Array [ {…}, {…} ]
​
0: Object { _id: "6205a8313fe12d6b4ec354c4", fullName: "Johnny Cochrane", contracts: {…} }
​​
_id: "6205a8313fe12d6b4ec354c4"
​​
contracts: Object { type: "Quarterly", hours: 120 }
​​
fullName: "Johnny Cochrane"
​​
<prototype>: Object { … }
​
1: Object { _id: "6217c1b73fe12d6b4ec3550e", fullName: "Sheila Thompson", contracts: {…} }

And here is where I’m assigning new fields thats throwing the error:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

useEffect(() => {
        if(data) {

            let dataArr = [...data]
        
            const contractsByMonth = (type, hours) => {
                if (type === "Quarterly") {
                let monthHours = hours / 3
                return +(Math.round(monthHours + "e+2")  + "e-2");
            }     
            }

            dataArr.map(i => {
                let monthly = contractsByMonth(i.contracts.type, i.contracts.hours)
                i.contracts = {type: i.contracts.type, monthHours: monthly, total: i.contracts.hours  } 

...
}, [data])

So I know the data is there, it is not in a string that needs to be parsed, and even trying to reassign it is not seeming to work. Appreciate any thoughts anyone has. Shouldnt be the issue, but I’m using RTK Query to get the data, but I use it all the time without this issue, my guess is that its treating the data as the original mongoose returned document.

EDIT

Adding more of the components code:

const HoursGraph = () => {
 const {id} = useAuth()
 const userId = id

...

const  [pullData, {data}]  = useGetSnapshotMutation({userId, isStart, isEnd}) 
// RTK Query mutation which pulls the data- its an aggregation and I pass criteria through the body, but I've done this plenty without issue

...
useEffect(() => {
 ...
if (index === 0) {
            start = new Date(end).setDate(1)
        } else if (index === 1) {
            const startMth = currentMth - 1
            console.log(currentMth, startMth)
            start = new Date(new Date(new Date(end).setMonth(startMth, 1)).setHours(0, 0, 0)).toISOString()
        } else if (index === 2) {
            const startMth = currentMth -2
            console.log(currentMth, startMth)
            start = new Date(new Date(new Date(end).setMonth(startMth, 1)).setHours(0, 0, 0)).toISOString()
        }
        setIsStart(start)
        setIsEnd(end)
}, [])

 useEffect(() => {
        if(isStart && isEnd && userId) {
            pullData({userId, isStart, isEnd})
        }
    }, [isStart, isEnd, userId])
    
    console.log("snapshot data: ", data) //this logs the data referenced above

 useEffect(() => {
        if(data) {

            let dataArr = [...data]
        
            const contractsByMonth = (type, hours) => {
                if (type === "Quarterly") {
                let monthHours = hours / 3
                return +(Math.round(monthHours + "e+2")  + "e-2");
            }     
            }

            dataArr.map(i => {
                let monthly = contractsByMonth(i.contracts.type, i.contracts.hours)
                i.contracts = {type: i.contracts.type, monthHours: monthly, total: i.contracts.hours  } //This throws the error

                let colors
                let sum

                let qtrSum = i.hours.reduce((acc, curr) => acc.count + curr.count)
                console.log("sum: ", qtrSum)
                const color= ['#73E078', '#26A69A', '#26C6DA', '#29B6F6']
                
                i.hours = i.hours.map(x => {return ( {date: x.date, count: x.count, month: monthly } )})
                i[colors] = color
                i[sum] = qtrSum
                })
                console.log(data)
...
}, [data])

>Solution :

Instead of assigning to i.contracts, which appears to be read-only, try

dataArr.map((i) => {
  const monthly = /*yourt code here*/
  const contracts = {...i.contracts, monthHours: monthly, total: i.contracts.hours} //this obviously has a different type than the original i.contracts, which is an issue you will still have to deal with
  return {...i, contracts};
})

This issue is probably that the contracts you’re trying to mutate on i is typed as read-only (and you’re trying to mutate it to a different type). RTK Query uses immer under the hood, which might protect you from the consequences of rewriting that property if you make the edit in the transformResponse field of your endpoint. It might not let you change the type in the process though.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading