Home > Back-end >  Remove text by clicking on it - React
Remove text by clicking on it - React

Time:07-24

I'm trying to start learning react but fail understanding basic logic. I have a todo list page, which works fine with a strike-through, but if I try to change the strike through to REMOVE instead, my app disappears on click. Here's my code, hopefully you can understand:

function Note({ notes, note, onClickSetter }) {
    const { input, id } = note
    const [strikeThrough, setStrikeThrough] = useState(false);

    function onNoteClick(event) {
        const { value, id } = event.target
        //setStrikeThrough((prev) => !prev) - the strike through which is canceled right now
        onClickSetter(prev => prev.filter(aNote => aNote.id !== id)) // why this doesn't work?
    }

    return (
        <>
            <h1 style={ strikeThrough ? {textDecoration: 'line-through'} : { textDecoration: 'none' }} id={id} onClick={onNoteClick}>{input}</h1>
        </>
    )
}

a little explanation on my props: notes - literally the list of notes which comes from a useState on father component (we shouldn't touch this from my understanding of react)

note - self note information

onClickSetter - the other part of useState, the setter one.

So on another words, I have the notes which holds all notes, and onClickSetter which is in another words is setNotes - both part of useState

on top of that I have a note information, because this is a note component

the father component:


function Body() {

    const [Notes, setNotes] = useState([])

    
    return (
        <div className='notes-body'>
            <NewNote onClickSetter={setNotes}/>
            {Notes.map((note) => { return <Note key={note.id} notes={Notes} note={note} onClickSetter={setNotes}/>})}
        </div>
    )
}

function NewNote({ onClickSetter }) {

    const [input, setInput] = useState('')

    function onInputChange(event) {
        const { value } = event.target
        setInput(value)
    }

    function onButtonClick(event) {
        onClickSetter((prev) => {
            try {
                return [...prev, {input: input, id: prev[prev.length-1].id 1}]
            }catch{
                return [{input: input, id: 0}]
            }
        })
        setInput('')
    }

    return (
        <>
            <Input placeholder="add new note" className='note-text' onChange={onInputChange} value={input}/>
            <Button className='btn btn-primary add-note' onClick={onButtonClick} />
        </>
    )
}

CodePudding user response:

The reason is that event.target.id is a string representing a number since all HTML attributes has the string type. Whilst in your data structure, the ID is a number. So, e.g. "1" vs 1. This can be hard to spot sometimes.

The easiest way to fix this is to add a parseInt to the right place to convert the string to a number:

  onClickSetter((prev) => prev.filter((aNote) => aNote.id !== parseInt(id)))

However, I also want to mention (and this is more advanced stuff but I like to get people on the right track :) ) that really, you shouldn't pass the whole setter down into the child component, but instead a callback called something like onRemoveNote that accept the note id and the actual filtering/removal would happen in the parent component.

This would be better placement of concerns. For now though, the above will work and I can help you out on stack overflow chat if needed :).

  • Related