smgeog
smgeog

Reputation: 15

Delete object from Firebase, React, ES6

[SOLVED]Look for the answer below

Having problem with deleting an object from firebase database, have experience with that but this time it is not working:

action:

export const firebase_db = firebase.database().ref();

export function deleteData(key) {
  return dispatch => firebase_db.child(key).remove(); 
}

reducer:

case DELETE_DATA:
    return _.omit(state, action.payload);

basic_list.js:

clickHandler() {
    this.props.deleteData();
}

And button:

        <td><button
            onClick = {this.clickHandler()}
            className="btn btn-outline-secondary btn-danger">
            Delete
        </button></td>

I should access key of firebase object and it is in this.props.data[post], but when I do that like this:

clickHandler() {
    this.props.deleteData(this.props.data[post]);
}

it says ReferenceError: post is not defined, then when do this in onClick:

onClick = {this.clickHandler(this.props.data[post])}

with:

clickHandler() {
    this.props.deleteData();
}

I have error Reference.child failed: First argument was an invalid path = "undefined". Paths must be non-empty strings and can't contain ".", "#", "$", "[", or "]"

and then when I try with backtick, as example:

clickHandler(key) {
    this.props.deleteData(`key`);
}

with

onClick = {this.clickHandler(this.props.data[post])}

I don't have any error, but nothing is happening...

maping looks like this:

renderData(DataRender) {
    if (_.isEmpty(this.props.data)) {
        return <td>Loading...</td>
    } else {
        return Object.keys(this.props.data).map((post, key) => (
        <tr key={key} post={post} id={key}>
            <td>{this.props.data[post].adress}</td>

button is in this map function, you can see how am I accessing value of adress, [post] is a hash of that object...

And if anyone asks, I have binded clickHandler in constructor,

Thank you!

EDIT: So now my action looks like this:

export function deleteData(key) {
  return dispatch => firebase_db.child(`${key}`).remove(); 
}

but when I try inserting hash with this.props.data[post] it says ReferenceError: post is not defined

Upvotes: 0

Views: 2762

Answers (2)

smgeog
smgeog

Reputation: 15

This answer is for easier reading of the solution and to see whole code!

So for the firebase database that looks like this: firebase database

proper way to delete object is:

action file: ...after importing firebase config file...

export const firebase_db = firebase.database().ref();

export const DELETE_DATA = 'DELETE_DATA';

export function deleteData(key) {
  return dispatch => firebase_db.child(`${key}`).remove(); 
}

reducer should be:

import {DELETE_DATA } from '../actions';
import _ from 'lodash';

case DELETE_DATA:
    return _.omit(state, action.payload);

next step is your component:

import your action:

import { deleteData } from '../actions/index';

you should bind action creators:

export default connect(mapStateToProps, {FetchData, deleteData})(BasicList);

I'm rendering data and taking one specific value from the database, you can see whole render function, maybe it can help you:

renderData(DataRender) {
    if (_.isEmpty(this.props.data)) {
        return <td>Loading...</td>
    } else {
        return Object.keys(this.props.data).map((post, key) => (
        <tr key={post} post={post} id={key}>
            <td>{this.props.data[post].adress}</td>
            <td>{this.props.data[post].city}</td>
            <td>{this.props.data[post].owner}</td>
            <td>
                <Link to={`/data/${post}`}>
                    detalis
                </Link>
            </td>
            <td><button
                onClick = {(e) => this.clickHandler(e, [post])}
                className="btn btn-outline-secondary btn-danger">
                Delete
            </button></td>
        </tr>
    ));
    }
}

here you can see few things, firstly, how to map over firebase database objects, then you can see how to go to the specific object with firebase hash as url (to={/data/${post}}) and finally, my own problem, onClick function, next steps for successful deleting an item:

create that clickHandler function, should look something like this:

clickHandler(e, data) {
    this.props.deleteData(data);
}

and you should bind that, can do in constructor:

constructor(props) {
    super(props);

    this.clickHandler = this.clickHandler.bind(this);
}

for this specific file, my import statements are:

import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import _ from 'lodash';

hope that I didn't forget something, also, look at the comments, there you can see some errors and solutions, please carefully read jpacareu answer, there is good explanation (and say thanks to jpacareu); if you have any question about this freely comment and if you have question for firebase database, comment with the link to your question.

Upvotes: 1

jpacareu
jpacareu

Reputation: 651

Well by seeing your method:

clickHandler() {
    this.props.deleteData(this.props.data[post]);
}

If it says that post is not defined, I think is expected because post is not in the scope of the method, unless you have it declared somewhere else in the file or in the global scope.

One more thing is that when using

<td><button
       onClick = {this.clickHandler()}
       className="btn btn-outline-secondary btn-danger">
       Delete
 </button></td>

The Event Handler onClick should receive a function to be called and this.clickHandler() is returning nothing (undefined), so that's why:

with onClick = {this.clickHandler(this.props.data[post])} I don't have any error, but nothing is happening...

Because you should use it like

onClick={this.clickHandler}

and if you want to pass the argument (considering that post is somehow defined)

onClick={(e) => this.clickHandler(e,this.props.data[post])}

and then:

clickHandler(e,data){
   // data = this.props.data[post]
   this.props.deleteData(data);
}

And dont forget to bind in the constructor, your method clickHandler to your component's scope with:

this.clickHandler = this.clickHandler.bind(this);

One more thing is that you are not dispatching any object from your actions so I don't know if you are actualy receiving any data (action object) in your reducers. I don't know if this would help you but is a start to check these things out.

Upvotes: 0

Related Questions