Passed method not working

Hi there,
-From the ‘child’ component below, when a user presses a button in the ‘render’ method, ‘addATask()’ is triggered.
-‘addATask’ method is supposed to create a simple form for a user to fill in some details. This it does very well.
-The save button on the form is supposed to update a state in the parent component. For testing though, it will trigger a simple alert from the parent component. Here’s where my code fails to do so.
-Sorry I couldn’t highlight important code lines, but I hope you can understand.

=> This is (a piece of) the Parent component:

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      newTasks: [{name: 'Add a task', category: 'All', id: 1}]
    }

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

  onSaveTask() {
    alert('Good to go');
  }

  render() {
    return (
      <div>
        <h1>My To-Do</h1>
        <div className="control-bar">
          {/* 'Add task' instance */}
          <Add onSave={this.onSaveTask} />

=> This is (a piece of) the Child component ()

class Add extends React.Component {
    constructor(props) {
        super(props);
        
        this.addATask = this.addATask.bind(this);
    }


    addATask() {
    let newSection = document.createElement('section');
    newSection.className = 'aTask';

    const form = '<section>' +
                    '<label>Task Name:</label>' +
                    '<input type="text" name="aName" value="" id="taskNameInput" />' +
                        '<p> </p>' +
                    '<label>Category:</label>' +
                    '<input type="text" name="aCategory" value="" id="taskCategoryInput" />' +
                        '<p> </p>' +
                    '<label>Due date</label>' +
                    '<input type="date" name="dueDate" />' +
                        '<p> </p>' + 
                    '<div className="optionArea">' +
                        '<button onClick={this.props.onSave}>Save</button>' +
                        '<button>Cancel</button>' +
                    '</div>' +
                '</section>'

    newSection.innerHTML = form;
    document.querySelector('.new-tasks_space').appendChild(newSection);

  }

    render() {
        return (
            <button class="add-button" type='button' onClick={this.addATask}>+ task</button>
        );

-Details on where and why I’m wrong will be really helpful. Thanks for your time!

Hi, looking at your code it seems that you’re missing a setState in your parent component and an event handler in your child component.
So in your parent component you can add this piece of code right after your constructor :

 saveTask(newTask) {
    this.setState({
      task: newTask
    });
  }

Then in your constructor use this for binding :

this.saveTask = this.saveTask.bind(this);

In your render method :

<Add onSave={this.saveTask} />

After this you will need an event handler in your Child component.

 handleSave(e) {
    const task = e.target.value;
    this.props.onSave(task);
  }

And you will need to bind it again.

this.handleSave = this.handleSave.bind(this);

In your Child’s render method :

<button onSave={this.handleSave}>Save</button>

You can try making these changes and let me know how it goes.

Hi, thanks for replying.

I’ve tried the method you gave me and it works. But, from the parent component, I’m trying to ‘push’ a new ‘task-object’ to the existing one and I can’t seem to do so with this.setState()

Something like this…


...

this.state = { newTasks: [ { name: 'task 1', category: 'school', id: 1 } ] }

...

To this…


...

this.state = { newTasks: [ { name: 'task 1', category: 'school', id: 1 }, { name: 'task 2', category: 'home', id: 2 } ] }

...

How can I accomplish this?

You probably need to use another function to add new tasks, it should look like this :

import { useState } from "react";

function AddTask() {
  const [tasks, setTasks] = useState([
    { desc: "task 1", id: 1 },
    { desc: "task 2", id: 2 },
  ]);

Don’t forget to import ‘useState’, you can do so when importing react like so :

import React, { useState } from 'react';

I hope that helps.