状态值在条件setState

时间:2020-04-19 18:13:13

标签: javascript reactjs react-hooks conditional-operator

我正在实现滑块组件。当用户单击向左或向右箭头时,它将通过给定scrollWidth来更改滚动值。我对此实施有疑问:

const Slider = (props) => {
  const [scrollValue, setScrollValue] = useState(0)
  const [containerDimensions, setWidths] = useState({ offsetWidth: 0, scrollWidth: 0 })
  const [activeLeft, setActiveLeftArrow] = useState(false)
  const [activeRight, setActiveRightArrow] = useState(true)

...

  const checkArrowDisable = () => {
    containerDimensions.offsetWidth + scrollValue < containerDimensions.scrollWidth ? setActiveRightArrow(true) : setActiveRightArrow(false)
    scrollValue > 0 ? setActiveLeftArrow(true) : setActiveLeftArrow(false)
  }

  const scrollRight = () => {
    const scrollWidth = sliderItem.current.offsetWidth
    sliderContainer.current.scrollLeft += scrollWidth
    setScrollValue(scrollValue + scrollWidth)
    checkArrowDisable()
  }

  const scrollLeft = () => {
    const scrollWidth = sliderItem.current.offsetWidth
    sliderContainer.current.scrollLeft -= scrollWidth
    setScrollValue(scrollValue - scrollWidth)
    checkArrowDisable()
  }

checkArrowDisable中,检查滚动和容器宽度值以隐藏/显示左箭头和右箭头。问题在于,通过此实现,activeLeftactiveRight的状态将在应有的状态下更新一个步骤。 checkArrowDisable函数有什么问题?

编辑:

解决此问题的关键是用新的更新值创建中间变量并将其传递给下一个函数。

  const scrollRight = () => {
    const scrollWidth = sliderItem.current.offsetWidth
    sliderContainer.current.scrollLeft += scrollWidth
    const updatedScrollValue = scrollValue + scrollWidth
    setScrollValue(updatedScrollValue)
    checkArrowDisable(updatedScrollValue)
  }

然后

  const checkArrowDisable = (newScrollValue) => {
    containerDimensions.offsetWidth + newScrollValue < containerDimensions.scrollWidth ? setActiveRightArrow(true) : setActiveRightArrow(false)
    newScrollValue > 0 ? setActiveLeftArrow(true) : setActiveLeftArrow(false)
  }

2 个答案:

答案 0 :(得分:1)

设置者是异步的。因此,不应在相同的功能或子功能中使用假定的设定值。我的意思是:

static void mergeIntelHexFiles(const char* aFile, const char* bFile, const char* mergedFile)
{
  FILE* readFileA  = fopen(aFile, "r");
  FILE* readFileB = fopen(bFile, "r");
  if (   (NULL != readFileA  )
      && (NULL != readFileB ))
  {
    FILE* writeFile = fopen(mergedFile, "w");
    if (NULL != writeFile)
    {
      char lineBuffer[MAX_PATH_LEN];

      while (NULL != fgets(lineBuffer, MAX_PATH_LEN, readFileA ))
      {
        if (NULL == strstr(lineBuffer, ":00000001FF"))
        { // it is not the last line of the file
          fputs(lineBuffer, writeFile); // copy the line without modification
        }
      }

      while (NULL != fgets(lineBuffer, MAX_PATH_LEN, readFileB ))
      {
        fputs(lineBuffer, writeFile); // copy the line without modification
      }

      fclose(writeFile);
    }
    fclose(readFileA);
    fclose(readFileB);
  }
}

我建议为 const scrollLeft = () => { const scrollWidth = sliderItem.current.offsetWidth sliderContainer.current.scrollLeft -= scrollWidth setScrollValue(scrollValue - scrollWidth) # scrollvalue not necessarily updated yet checkArrowDisable() # uses scrollvalue which is either updated or not } 使用一个变量并将其传递给scrollValue - scrollWidth函数

答案 1 :(得分:0)

您的checkArrowDisable函数不是必需的,因为这些单独的方法可以在每个scroll函数中以一种方式完成。

相反,这样做:

const scrollRight = () => {
  const scrollWidth = sliderItem.current.offsetWidth
  sliderContainer.current.scrollLeft += scrollWidth
  const newScrollValue = scrollValue - scrollWidth
  setScrollValue(newScrollValue)
  setActiveRightArrow(containerDimensions.offsetWidth + newScrollValue < containerDimensions.scrollWidth)
}

const scrollLeft = () => {
  const scrollWidth = sliderItem.current.offsetWidth
  sliderContainer.current.scrollLeft -= scrollWidth
  const newScrollValue = scrollValue - scrollWidth
  setScrollValue(newScrollValue)
  setActiveLeftArrow(newScrollValue > 0)
}

问题是useState挂钩设置器异步运行。因此,当您尝试在scrollValue中使用checkArrowDisable时,它在更新之前仍在使用先前的scrollValue

按照我上面的建议进行操作即可解决此问题。