Search code examples
javascriptreactjsreact-dom

Cant update tasks


I have tasks and by clicking editing button or label it enable editing mode for task by swapping className. I want not to just swap className but also close editing mode for all tasks. But It seems that in this way React update object 'lists', but not actually rerender other tasks, only that clicked This my App JS:

.task{
    display: block;
}
.textfield{
    display: none;
}

li.editing .task{display: none;}
li.editing  .textfield{
    display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
import React, {useState} from 'react';
import { v4 as uuidv4 } from 'uuid';
import Task from './Task'


export default function App() {
const [list, setNewList] = useState(sampleList)
let newTask={
      liId:uuidv4(),
      liName:'Place name of Task here...',
      editingActive:false
    } 

function setEditingLi(newName,id,editingActive){
  if (editingActive){editingActive=false}
  else{editingActive=true}
  let newList=[...list]
    let index=newList.findIndex(li=>li.liId===id)
        newList[index].liName=newName
        newList[index].editingActive=editingActive
  setNewList(newList)
}    

function toRepayActiveEditingLi(){
    let newLists=list.map(task=>{
      task.editingActive=false
    return task
    })
    setNewList(newLists)
}    

  return (
    <div>
      <input onClick={()=>setNewList([...list,newTask])}
        type="submit" value="Add Task" id="do_form"
      />
      <br/>
      <main id="general">
        <ul>
          {list.map(task=>{
                  return <Task
                    key={task.liId} toRepayActiveEditingLi={toRepayActiveEditingLi} 
                    setEditingLi={setEditingLi}{...task}
                  /> 
              })}
        </ul>
      </main>
      <br/><br/><br/><br/>
    </div>
  );
  }
  const sampleList=[]

This is my Task component:

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
import React, { useState} from 'react'

export default function Task(props) {
    const {
        liId,
        liName,
        editingActive,
        toRepayActiveEditingLi,
        setEditingLi} =props
    const [liClass, toggleLiClass] = useState('li')
    const [buttonName, toggleButtonName] = useState('edit')
    const [currentInputValue, setInputValue] = useState('')
    
    function handleToggleEditingClass(){
        toRepayActiveEditingLi()
        if(editingActive){
            let value = currentInputValue
                toggleLiClass('li')
                toggleButtonName('edit')
                if(value.trim()){
                    setEditingLi(currentInputValue,liId,editingActive)
                }
                else{
                    setEditingLi(liName,liId,editingActive)
                } 
        }else{
            toggleLiClass('li editing')
            toggleButtonName('save')
            setEditingLi(liName,liId,editingActive) 
        }
    }

    return (
        <li className={liClass} id={liId}>
        <label className="task"
            onClick={handleToggleEditingClass}
        >{liName}</label>
        <textarea type="text" className="textfield"
            onChange={(e)=>setInputValue(e.target.value)} defaultValue={liName}
        ></textarea>
        <button 
            onClick={handleToggleEditingClass}
        >{buttonName}</button>
    </li>
    )
}


Solution

  • From what I could extract from your question after playing with the sandbox I believe you want to toggle off the edit mode for other tasks when selecting any new task to edit.

    You can add an effect to Task to move the logic of toggling this state when the editingActive prop is updated.

    useEffect(() => {
      if (editingActive) {
        toggleLiClass("li editing");
        toggleButtonName("save");
      } else {
        toggleLiClass("li");
        toggleButtonName("edit");
      }
    }, [editingActive]);
    
    function handleToggleEditingClass() {
      toRepayActiveEditingLi();
      if (editingActive) {
        let value = currentInputValue;
        if (value.trim()) {
          setEditingLi(currentInputValue, liId, editingActive);
        } else {
          setEditingLi(liName, liId, editingActive);
        }
      } else {
        setEditingLi(liName, liId, editingActive);
      }
    }
    

    Edit charming-cdn-y73kt