问题
Im running a react app with Firebase in the back. I have an endpoint "/items".
When I invoke a DELETE request through Axios, the database reflects the correct data. However, after the DELETE request when I invoke a GET request to retrieve updated "items" I get a null reference where the deleted item was, leading to a null reference error.
EXAMPLE
-Original [item1, item2, item3]
*Delete item2
-Get
- [item1, null, item3]
However on Firebase it is reflected correctly..
class VendingMachine extends Component {
state = {
balance: "",
items: [],
}
getItems = () => {
axios.get('items.json')
.then(response => {
if (response.data) {
this.setState({ items: Object.values(response.data) });
}
})
}
deleteItemHandler = (id) => {
axios.delete('/items/' + id + '.json')
.then((response) => {
this.getItems();
});
}
Put Request is in another component..
class NewItem extends Component {
errorElement = React.createRef();
state = {
newItem: {
name: "",
position: null,
price: "",
image: ""
},
showError: false
};
addItemHandler = () => {
if (this.props.items.length === 9) {
this.setState({ showError: true });
return;
}
const newItem = {
id: this.props.items.length,
name: this.state.newItem.name,
price: this.state.newItem.price,
image: this.state.newItem.image,
position: this.props.items.length
}
console.log(newItem);
axios.put('/items/' + newItem.id + '.json', newItem)
.then(response => {
this.props.updateItems()
})
.catch(error => console.log(error));
}
回答1:
This is the expected behavior when you store arrays in Firebase.
When you store:
["item1", "item2", "item3"]
The Firebase Database server actually stores it as:
{
"0": "item1",
"1": "item2",
"2": "item3"
}
And then means that when you delete item2
, you end up with:
{
"0": "item1",
null,
"2": "item3"
}
Which the Firebase client then translates back to:
["item1", null, "item3"]
You have two options:
- Always update the entire array
- Use a set instead of an array
Always update the entire array
If you want to keep storing the items as an array, you will have to renumber the index for all items after the ones you remove. So that means that any update to an array, means you need to read-and-then-write the entire array.
Use a set instead of an array
But you may not actually be storing an array. Many developers use arrays to store set-like data structures, i.e. unordered collections of unique items. For example: does ["item3", "item2", "item1"]
have the same meaning at ["item1", "item2", "item3"]
? And is ["item1", "item1", "item2", "item3"]
actually illegal in your app? If so, you're looking at a set-like data structure, which in Firebase is better mapped to:
{
"item1": true,
"item2": true,
"item3": true
}
The true
value is meaningless and only needed because Firebase won't store a key without a value. But aside from that, this is the best structure to store such a set-like collection. And if you remove item2
from this, Firebase will simply return the object without that key:
{
"item1": true,
"item2": true,
"item3": true
}
For more on this, also see:
- Best Practices: Arrays in Firebase
- Firebase query if child of child contains a value
来源:https://stackoverflow.com/questions/54138520/firebase-returning-null-references-when-get-after-delete