简体   繁体   English

React usecallback 不遵守由子函数引起的依赖项更改

[英]React usecallback not honoring dependency change caused by child function

Hopefully someone can help me with this, I will be quite grateful.希望有人可以帮助我,我将不胜感激。 I searched though previously answered questions and I can't find something exactly quite like this.我搜索了以前回答过的问题,但找不到完全像这样的东西。

In a nutshell:简而言之:

I have a useCallback react hook which renders a set of buttons.我有一个 useCallback 反应挂钩,它呈现一组按钮。 When one of those buttons are clicked, I need the whole function to re-render to reflect the desired changes.单击其中一个按钮时,我需要重新呈现整个功能以反映所需的更改。 As near as I can tell, I have all the necessary dependencies to achieve this but it's now happening.据我所知,我拥有实现此目标所需的所有依赖项,但它正在发生。 When I trigger a re-render via other action, the updates are there.当我通过其他操作触发重新渲染时,更新就在那里。

This main callback function is being called inside the base render.这个主要的回调函数在基础渲染中被调用。 Clicking the rendered button does not cause it to re-render.单击呈现的按钮不会导致它重新呈现。 What gives??是什么赋予了??

  const [pendingArticles, setPendingArticles] = useState([]);
  const [persons, setPersons] = useState([]);

  const renderArticlePieces = useCallback(() => {
    const selectedArticle = pendingArticles.find(article => article.selected);

    function assignArticlePieceToPerson(pieceId) {
      console.log(pendingArticles);
      const selectedArticleIndex = _.findIndex(pendingArticles, { selected: true });

      pendingArticles[selectedArticleIndex].json_content[pieceId].speaker = selectedPerson.id;

      setPendingArticles(pendingArticles);
    }

    function renderPersonAssignmentButtons(pieceId) {
      const currentPiece = pendingArticles.find(article => article.selected).json_content[pieceId];
      if (currentPiece.speaker) {
        return 'Assigned'
      }
      return personsAvailableToAssign.map((person, dex) => {
        return (
          <Button key={dex} onClick={() => assignArticlePieceToPerson(pieceId)}>{`${person.first_name} ${person.last_name}`}</Button>
        )
      }).concat(
        <Button key={personsAvailableToAssign.length + 1}>Other</Button>
      )
    }


    return selectedArticle?.json_content.map((item, dex) => {
      return (
        <div key={dex} style={{ backgroundColor: "#c7c7c7", borderRadius: "5px", padding: "5px", margin: "5px" }}>
          <div>
            Assign to:
            {renderPersonAssignmentButtons(dex)}
          </div>
          <div>{item.content}</div>
        </div>
      )
    })
  }, [pendingArticles, setPendingArticles, personsAvailableToAssign, selectedPerson, ])

The problem might be, that React uses a "shallow" comparison to check if something in the state changes.问题可能是,React 使用“浅”比较来检查状态中的某些内容是否发生了变化。 That means React won't go into your array and check each single array entry if it has changed.这意味着 React 不会进入您的数组并检查每个数组条目是否已更改。

Because you are mutating your existing array, React won't notice the changes.因为你正在改变你现有的数组,React 不会注意到这些变化。 Instead you should create a new array, for example using the spread-syntax:相反,您应该创建一个新数组,例如使用扩展语法:

let new_pending_articles = [...pendingArticles];
new_pending_articles[selectedArticleIndex].json_content[pieceId].speaker = selectedPerson.id;
setPendingArticles(new_pending_articles);

This way, because you are not mutating the array but completely replacing it, React should notice the change and trigger a re-render.这样,因为你不是在改变数组而是完全替换它,React 应该注意到变化并触发重新渲染。 Check this post as well: React doesn't rerender on an array state update还要检查这篇文章: React doesn't rerender on an array state update

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM