0

I am working on a tasklist page. The main page has a form in which the user would add the task and click on the add task button and the corresponding task would be appended to the "todo-task" div. I am using my own created react element (Do laundry is just for example) which returns a checkbox followed by the text passed as prop. In the following code I am trying to append at the end of our todo-task div but it is showing me some error. Is my approach right? If not what approach should I take?

import React,{useState} from 'react'
import './Tasklist.css'
import Button from 'react-bootstrap/Button';
import AddBoxIcon from '@material-ui/icons/AddBox';
import Checkbox from '@material-ui/core/Checkbox';
import Task from './Task.js';

function Tasklist() {
const [task, settask] = useState("")

let pendingTask = document.getElementById('pending-task')
let doneTask = document.getElementById('done-task')

const addTask = (event)=>{
    event.preventDefault()
    let tmp_text=task.trim()

    if(tmp_text==="")return

    let task_tmp = document.createElement(<Task text={tmp_text} />);
    pendingTask.appendChild(task_tmp);
    settask("");
}

const keyDownEvent=(e)=>{
    let key=e.key

    if(key==='Enter' && !e.shiftKey)addTask(e);
}
return (
    <>
        <div className="add-task">
            <form >
                <textarea 
                    type="text" 
                    value={task}
                    rows={1}
                    placeholder="Add Task" 
                    onChange={(e)=>settask(e.target.value)}
                    onKeyDown={keyDownEvent}
                    />
                <Button variant="outline-primary" onClick={addTask}>
                    <AddBoxIcon /> Add Task
                </Button>
            </form>
        </div>
        <div className="todo-task" id="pending-task">

        </div>
        
        <Task text="Enjjoyyyy!!!" />

        <hr />

        <div className="done-task" id = "done-task">
            <ul id="done-task-list">

            </ul>
        </div> 
    </>
)
}

export default Tasklist
  • What error is being shown? – Andy Jul 15 '21 at 16:25
  • You've got another good answer below, but it's effectively the same as yesterday's answers to the same question: [How to add our own react element?](https://stackoverflow.com/questions/68383189/how-to-add-our-own-react-element). Is there something still unclear? – Daniel Beck Jul 15 '21 at 16:37

1 Answers1

1

You're going about this in a fundamentally incorrect way, so it's not a quick fix. Now is the time to take a big step back and start over on your component.

What you're currently trying to do is modify the DOM directly. Don't do that in React. What you should instead be doing is maintaining state.

Instead of trying to directly create an element and add it to the DOM, create a record and update state with that record. This is an entirely separate task than rendering the DOM. The actual rendering is done based on that current state.

Currently in your state you have "a task". But you're trying to build functionality to add more tasks. So really your state should have a list of tasks, and you can add to that list. (Which can be in addition to the single task, of course. You can use useState as many times as you like.)

For example, consider state like this:

const [tasks, setTasks] = useState([]);

Then add a task in your button click handler:

const addTask = (event)=>{
    event.preventDefault();
    let tmp_text=task.trim();
    if(tmp_text==="") return;

    setTasks([...tasks, tmp_task]); // <--- here
    settask("");
}

This keeps a running array of the tasks being stored.

Then in the rendering, you would .map over those tasks to show them:

<div className="todo-task" id="pending-task">
    {tasks.map((t, i) => (
        <Task key={i} text={t} />
    ))}
</div>
David
  • 208,112
  • 36
  • 198
  • 279