Reputation: 143
I am getting this error when fetching data from firebase and pushing the data into an array. Here I define a temp array when I am pushing data inside firebase onValue into this temp array I am getting this error Uncaught TypeError: Cannot add property 0, object is not extensible at Array.push. Here is my code
function Room() {
const [textInput, setTextInput] = useState('');
const temp = [];
const handleTextInputChange = (event) => {
setTextInput(event.target.value);
};
const handleSubmit = () => {
console.log('here goes');
if (textInput !== '') {
const refer = ref(database, 'rooms/');
push(refer, textInput).then(() => {
setTextInput('');
toast.success('Added Successfully!');
});
}
};
useEffect(() => {
const refer = ref(database, 'rooms/');
onValue(refer, (snap) => {
snap.forEach((child) => {
console.log(child.val() + child.key);
// I am getting error in this line
temp.push({ id: child.key, firstName: child.val() });
});
});
}, []);
return (
<div>
<Grid item xs={12}>
<SubCard title="Room List">
<div style={{ height: 400, width: '100%' }}>
<DataGrid
rows={temp}
columns={columns}
pageSize={5}
rowsPerPageOptions={[5]}
components={{
Toolbar: CustomToolbar
}}
/>
</div>
</SubCard>
</Grid>
</div>
)
Upvotes: 7
Views: 19477
Reputation: 1420
The array is read only so what I do is just add a spread operator to it.
...
documents: [...d.distribution.documents],
...
Alternaively this worked as well
...
documents: d.distribution.documents.concat([]),
...
Upvotes: 1
Reputation: 3032
Thanks for the answer TJ Crowder, it helped me to understand that the real problem is not the object that you are going to pass the value, but the original object, because it is passed by reference.
So, when you have the error
object is not extensible at array
The solution is to copy the values of the original object to the target, not just assign them with the equals (=) operator.
for example
targetObject.nodes.map( (newNode: any) => {
//here I create a new object and enrich it with an array and a boolean
let newFullNode = Object.assign({}, newNode, {nodes: [] , hasChildren:true});
targetObject.nodes.push(newFullNode);
});
I update the targetObject later on, and when I was updating it, only then I was getting the error, which was misleading me.
Upvotes: 0
Reputation: 1075467
The error you're getting is what you get when you try to push to a frozen array:
const temp = Object.freeze([]);
temp.push(42);
You've shown that you're passing the array to DataGrid
as rows
. Apparently, DataGrid
freezes the array, presumably because it needs to know that the contents of it don't change.
If you want to change those contents, you'll need to store temp
in state and re-render after adding to it; see ***
comments (I've also renamed temp
to dataGridRows
):
function Room() {
const [textInput, setTextInput] = useState('');
// *** Store it in state
const [dataGridRows, setDataGridRows] = useState([]);
const handleTextInputChange = (event) => {
setTextInput(event.target.value);
};
const handleSubmit = () => {
console.log('here goes');
if (textInput !== '') {
const refer = ref(database, 'rooms/');
push(refer, textInput).then(() => {
setTextInput('');
toast.success('Added Successfully!');
});
}
};
useEffect(() => {
const refer = ref(database, 'rooms/');
onValue(refer, (snap) => {
snap.forEach((child) => {
console.log(child.val() + child.key);
// *** Add to it in state; this will cause a re-render
// so DataGrid picks up the change
setDataGridRows(dataGridRows => [...dataGridRows, { id: child.key, firstName: child.val() }];
});
});
}, []);
return (
<div>
<Grid item xs={12}>
<SubCard title="Room List">
<div style={{ height: 400, width: '100%' }}>
<DataGrid
rows={dataGridRows}
columns={columns}
pageSize={5}
rowsPerPageOptions={[5]}
components={{
Toolbar: CustomToolbar
}}
/>
</div>
</SubCard>
</Grid>
</div>
)
}
Upvotes: 11