簡體   English   中英

由於 useRef,反應 useState 未更新

[英]React useState not updating because of useRef

我的反應代碼遇到了一個非常奇怪的問題:useState 沒有更新視圖,在嘗試了所有內容之后,問題仍然存在。 我做了一個簡單的代碼來解釋這個問題:

 function(){ const [enterJob, setEnterJob] = useState(false); const [jobSelection, setJobSelection] = useState(Array(someList.length).fill(false)); const jobRef = useRef(); const handleJobClick = i => { const n = parseInt(i.target.id.charAt(0)); // the list is small enough to allow this let c = jobSelection; c[n] = !c[n]; setJobSelection(c); }; const handleMouse = (e) =>{ if (!jobRef.current.contains(e.target)){ setEnterJob(false); }; }; useEffect(() => { window.addEventListener("mousedown", handleMouse); return () => window.removeEventListener("mousedown", handleMouse); }); return( <div ref={jobRef}> <input onFocus={()=> setEnterJob(true)} /> <div style={{display: `${enterJob ? 'flex' : 'none'}`}} > <ul> { someList.map((item,index)=> <li id={`${index}`} onClick={handleJobClick}> {jobSelection[index] ? item : "you clicked on the button"} </li> )} </ul> </div> </div> ) }

一些解釋:我正在使用 UseEffect 和 useRef 創建一個下拉菜單,當您在容器外單擊時該菜單會消失。 現在,當我想單擊此下拉菜單的值時,它不會更新 DOM,而我正在使用 useState 更新負責更改的字符串的值。

提前謝謝你,查貝爾

問題是您正在改變jobSelection而不是創建新對象。 如果對象具有與以前相同的引用,react 將跳過重新渲染:

 const handleJobClick = i => {
        const n = parseInt(i.target.id.charAt(0)); // the list is small enough to allow this
        let c = [...jobSelection]; // Create a new array
        c[n] = !c[n];
        setJobSelection(c);
    };

問題

如果我理解您的問題,那么我相信這是因為您正在直接改變您的狀態。

const handleJobClick = i => {
    const n = parseInt(i.target.id.charAt(0)); // the list is small enough to allow this
    let c = jobSelection;
    c[n] = !c[n]; // <-- mutation!
    setJobSelection(c);
};

您還缺少映射列表項上的反應鍵。

解決方案

由於下一個狀態取決於前一個狀態,因此您應該先使用功能狀態更新來復制您的狀態,然后再更新它。

我建議:

  1. handleJobClick轉換為直接使用索引,一個handleJobClick函數可以干凈地處理這個
  2. 向映射的列表項添加反應鍵

代碼

const handleJobClick = index => () => {
  setJobSelection(jobSelection => jobSelection.map(
    (selection, i) => index === i ? !selection : selection // <-- toggle selection at matched index
  );
};

...

<ul>
  {someList.map((item, index)=> (
    <li
     key={index} // <-- index as react key, ok since not adding/removing/sorting jobs
     onClick={handleJobClick(index)} // <-- pass index to handler
    >
      {jobSelection[index] ? item : "you clicked on the button"}
    </li>
  ))}
</ul>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM