3

So I am running into a slight issue in regards to this basic task app I am creating with React, Firebase, and Node. I have the working version hosted on heroku(will post link below) so you can use it to see what I mean.

My Issue

If you visit the link to my app, you can see that when you initially click the get tasks button, the tasks do not get loaded to the screen. It takes two clicks to get the list to populate to the screen.

Also, when you click the close icon to try to remove the specific task, well... you will see with your own two eyes what happens, lol.

My Thoughts Although I am happy that it atleast works, I feel as if the main culprit is the code I am creating inside of the grabTasks function. Don't ask why I created a random empty array with the variable name x, I have no clue either, it was the only way I could get it to work. I've read all the firebase docs, so I am hoping someone here can enlighten me on what the issue is, and maybe suggest a better way to go about this. Code & Links below.

Link to working Heroku App

App.js

// App.js
export default class App extends Component {
  constructor(props) {
    super(props);

    this.state = { tasks: [] };
    this.grabTasks = this.grabTasks.bind(this);
    this.handleDelete = this.handleDelete.bind(this);
  }

  // Grabs the list of tasks from the firebase database
  // and then sets the state to x.
  grabTasks() {
    var x = [];
    db.ref('tasks').on('value', function(snapshot) {
       return x = snapshot.val();
    });
    this.setState({ tasks : x });
  }

  // In charge of removing the task items when they are clicked.
  // This function is passed to TaskItems via props
  handleDelete(taskToDelete) {
       var newTasks = _.reject(this.state.tasks, function(task) {
           return task == taskToDelete
       });
       this.setState({tasks: newTasks});
     }

  render() {
    return (
      <div id="wrapper">
        <div id="navigation">
          <Navbar />
        </div>
        <div id="content">
          <div className="container">
            <div className="row">
              <h2>Tasks</h2>
              <div onClick={this.grabTasks} className="btn">Get Tasks</div>
              <TaskItems tasks={this.state.tasks} handleDelete={this.handleDelete} />
            </div>
          </div>
        </div>
      </div>
    )
  }
}

TaskItems.js

// TaskItems Child Component
const TaskItems = (props) => {
  var hello = props.tasks.map((task,index) => {
    return(
      <li className="collection-item" key={index}>
        {task}
        <a onClick={props.handleDelete.bind(this, task)}>
          <i className="fa fa-times-circle remove-task" aria-hidden="true"></i>
        </a>
      </li>
    );
  });

  return (
    <div>
      <ul className="collection">
        {hello}
      </ul>
    </div>
  );
}

export default TaskItems

4
  • Why are you adding snippets that don't run? Commented Sep 4, 2016 at 1:46
  • They are not meant to be run, I have the full app working in the heroku link. Is there a better way that I should be inserting code that does not have the intention of being run? Commented Sep 4, 2016 at 1:48
  • 1
    Just using code blocks (as in Phi Nguyen's answer). Snippets do allow for an easier copying into an answer, but they are intended as a jsFiddle replacement, to demonstrate working code. Commented Sep 4, 2016 at 1:50
  • Roger that. Thanks. Commented Sep 4, 2016 at 2:09

1 Answer 1

2

Your db.ref('tasks') is an async method. You shouldn't think it as sync. Try this:

grabTasks() {
 var that = this;
 db.ref('tasks').on('value', function(snapshot) {
   var x = snapshop.val();
   that.setState({tasks : x})
 });
}

To get those tasks when the screen is loaded :

componentDidMount(){
  this.grabTasks();
}
Sign up to request clarification or add additional context in comments.

1 Comment

Wow, thanks a lot. This is life changing. I've been stuck on this basic concept for quite a while. Thanks. The added componentDidMount is a huge help as well.

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.