状态改变后反应不渲染列表

React not rendering list after the state is changed

我正在创建一个简单的跟踪器来记录所有完成的活动。这是我的第一个反应项目。我创建了三种状态,一种用于存储所有项目(状态名称为列表),一种用于待处理项目(状态名称为待定),一种用于完成项目(状态名称为已完成)。这些项目有一个按钮,单击该按钮会将其标记为完成状态,反之亦然。它正在完全渲染主列表的项目。但对于其他两个,它没有渲染。当我检查 React 开发人员工具时,它工作正常,即它正在添加到待处理列表或完成列表中。但它不是在屏幕上编译它们。列表中已经填满了项目。为了以防万一,我添加了所有代码。

function Filters(props){
  const [completed, setCompleted] = useState([]);
  const [pending, setPending] = useState([]);
  const [state, setState] = useState("None");
  const [list,setList] = useState([]);

  function viewState(){
    setState("View-all");
  }

   //it is getting the clicked item id and marking it complete in main list
  function markComplete(id){
    list.map((items,index)=>{
      if(index===id){
        if(items.done===true)
          items.done = false;
        else{
          items.done=true;
        }
      }
    })
  }

//i am simply scanning the main list and the items which are pending will be added to this list. //this happens whenever the person click on pending button
 function pendingState(){
    setState("pending-all");
    setPending([]);
    list.map(items=>{
      if(items.done!==true){
        setPending(prev=>{
          return [...prev,items];
        })
      }
    })
  }

  function completedState(){
    setState("completed-all");
    setCompleted([]);
    list.map(items=>{
      if(items.done===true){
        setCompleted(prev=>{
          return [...prev,items];
        })
      }
    })
  }

 return (
    <div>
      <div className="input-section">
        <Note setList={setList} />
      </div>
      <button type="button" onClick={viewState} >View All</button>
      <button type="button" onClick={completedState}>Completed</button>
      <button type="button" onClick={pendingState}>Pending</button>
      <div>
        {
          (()=>{
            if(state==="View-all")
            {
              return (
                <div>
                  <h1>Working {completed}</h1>
                  {(list).map((items,index)=>
                    {
                    return (

                      <Excercise
                        key={index}
                        id={index}
                        title={items.name}
                        list={props.list}
                        setList={props.setList}
                        content={items.desp}
                        markComplete={markComplete}
                        />
                    )
                  })}
                </div>
              )
            }
            else if(state==="completed-all")
            {
              return (
                <div>
                {completed.map((items,index)=>{
                  <Excercise
                    key={index}
                    id={index}
                    title={items.name}
                    list={props.list}
                    setList={props.setList}
                    content={items.desp}
                    markComplete={markComplete}
                    />
                })}
                </div>
              )
            }
  })()
        }

      </div>


    </div>);
}



请帮忙。谢谢。

嗨@DREW 函数代码:

  function markComplete(id){
    setList(lists=>{
      lists.map(item=>{
      return item.id===id ?{...item,done: !item.done} : (item);})
      }
      )
  }

当我使用它而不是

 const markComplete = (id) => {
    setList((list) =>
      list.map((item) =>
        item.id === id
          ? {
              ...item,
              done: !item.done
            }
          : item
      )
    );
  };

显示“无法读取未定义的属性(读取 'filter')” 两者不一样。如果不是,我做错了什么。不好意思打扰了这么多次,我刚开始用react。

尝试在useEffect

中添加依赖

在此函数中,您正在改变一个状态,因此您需要使用 setState 函数,在本例中为 setList()。

 function markComplete(id){
    list.map((items,index)=>{
      if(index===id){
        if(items.done===true)
          items.done = false;
        else{
          items.done=true;
        }
      }
    })
  }

因此,实现此功能的更好方法可能是,请记住,每当您需要更新状态时,您不想直接更改状态,相反,您应该制作一个副本并将状态设置为该副本

function markComplete(id){
  const newList = [...list];

  newList.map((items,index)=>{
      if(index===id){
        if(items.done===true)
          items.done = false;
        else{
          items.done=true;
        }
      }
  }
  setList(newList)
}

你的应用没有更新的原因是因为当你的状态改变时反应不是re-rendering它再次。

所以使用useEffect有很多钩子可以根据需要使用

试试把这行代码

useEffect( ( ) => {
  
   console.log( 'Check console' );

}, [ dependency_here ] );

dependency_here中尝试逐一添加statecompletedpending,然后查看结果。 您还可以添加多个依赖项,例如 [ state, pending, etc.. ];

自己尝试一下就会理解得更快。

希望提示对您有所帮助!

我认为你把事情复杂化了一点。您只需要一个数组来存储练习,“待定”和“完成”状态很容易从 list 状态和 state 过滤器状态值中导出。

问题

  • markComplete 回调正在改变 list 状态。更新 list 状态时,不仅需要新的数组引用,而且正在更新的元素也需要新的元素对象引用。
  • 使用较差的布尔比较来设置布尔值。您可以切换布尔值或将值设置为布尔表达式的结果。
  • 使用 viewStatependingStatecompletedState 处理程序来简单地设置过滤器值,然后通过添加内联 filter 在渲染时派生计算状态功能。
  • 使用练习 id 属性 作为 React 键 作为 属性 用于切换已完成的 (done) 状态。

解决方案

function Filters(props) {
  const [state, setState] = useState("None");
  const [list, setList] = useState([
    ...
  ]);

  function viewState() {
    setState("View-all");
  }

  function pendingState() {
    setState("pending-all");
  }

  function completedState() {
    setState("completed-all");
  }

  const markComplete = (id) => {
    setList((list) =>
      list.map((item) =>
        item.id === id
          ? {
              ...item,
              done: !item.done
            }
          : item
      )
    );
  };

  return (
    <div>
      <div className="input-section">
        <Note setList={setList} />
      </div>
      <button type="button" onClick={viewState}>
        View All
      </button>
      <button type="button" onClick={completedState}>
        Completed
      </button>
      <button type="button" onClick={pendingState}>
        Pending
      </button>
      <div>
        {list
          .filter((item) => {
            if (state === "pending-all") {
              return !item.done;
            } else if (state === "completed-all") {
              return item.done;
            }
            return true;
          })
          .map((item) => (
            <Excercise
              key={item.id}
              id={item.id}
              done={item.done}
              title={item.name}
              content={item.desp}
              markComplete={markComplete}
            />
          ))}
      </div>
    </div>
  );
}