0

[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

4
  • post is an object? Your best bet is to look at what this.props.data has (property-wise) and then double-check your accessor. To access a property like this.props.data[something], [something] must be a string or resolve to a string Commented Aug 13, 2018 at 22:24
  • As mentioned in the post, I'm accessing hash value with this.props.data[post], but in the same function it says post is not defined (can get specific object value, make Link to every object but can't put it in the clickHandler), thats why I don't understand what is happening Commented Aug 13, 2018 at 22:33
  • I think there could be a few different possible issues here. Does your code actually reach your action? Commented Aug 13, 2018 at 22:38
  • It reaches action because when for any changes in action it gives different/similar errors, as example, when I make basic button onClick function and change action, then it gives me error from action Commented Aug 14, 2018 at 6:55

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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.

6 Comments

With my action that looks like this: export function deleteData(key) { return dispatch => firebase_db.child(${key}).remove(); } and with your suggestion, there's error Error: Reference.child failed: First argument was an invalid path = "[object Object]". Paths must be non-empty strings and can't contain ".", "#", "$", "[", or "]"
I want to say again, in that map function I have <td></td> elements where I'm accessing values with this: {this.props.data[post].adress}, as shown in the question, after that I have Link element where I'm accessing specific post with this:to={backticks*/data/${post}backticks*}, next element is button where I can't send hash, but like mentioned, it is successfuly sent with {post} or this.props.data[post]. That's what I don't understand. *backticks > `(hope that you understand this backticks confusion)
UPDATE: now when I console.log this data: onClick = {(e) => this.clickHandler(e, (this.props.data[post]))} it gives me that specific object, so obviously now it can read hash property, but still have that error from comment before...
SOLVED: the solution is onClick = {(e) => this.clickHandler(e, ([post]))}
Good notice, it's working without those parenthesis, probably leftover from console.loging... also, I will write new answer to put everything together so it is easier to read and accept your answer beacuse it was most helpful and most of the thing... thanks!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.