【问题标题】:How to conditionally reset state count with react hooks如何使用反应挂钩有条件地重置状态计数
【发布时间】:2021-05-19 23:30:54
【问题描述】:

在用户提交我的表单后,handleSubmit 函数运行并计算在我的div 中显示所有搜索结果的类名称包含“show”的li 元素的数量。它将这些计数与setStoreCount(prevCount => prevCount + 1) 相加,我更新了我的FAQ {searchCount} UI,显示搜索结果的数量与

useEffect(() => {
  setSearchCount(storeCount) // collect all storeCount
}, [storeCount])

问题:假设第一次搜索得到 5 个结果。

然后 UI 将显示FAQ 5。如果您再次搜索相同的内容,您仍然会得到 5 个结果,并且希望 UI 仍然显示 FAQ 5,但是因为 storeCount 无法重置为 0 它显示 FAQ 10 (5 + 5) 然后 @987654332 @ (5 + 5 + 5) 等等。

因为每当storeCount 更改时我的useEffect 都会有条件地运行,所以我无法将其重置为0,因为那样我将始终显示FAQ 0

如何在下面的代码中刷新每次搜索的计数时显示搜索结果的数量?

import React, { useState, useRef, useEffect } from 'react'

import ContentsWrap from '../../components/contents-wrap'
import FrequentList from './tabs/frequent'
import EstimateList from './tabs/estimate'
import ReturnList from './tabs/return'
import EtcList from './tabs/etc'
import SubsidiaryList from './tabs/subsidiary'
import ServiceList from './tabs/service'
import InList from './tabs/in'
import OutList from './tabs/out'

import styles from './index.module.scss'

export default function FAQ () {
  const [tab, setTab] = useState('frequent')
  const [storeText, setStoreText] = useState('') // stores searchbar text as user types
  const [searchText, setSearchText] = useState('') // sends searchbar text to List component props on form submit
  const [storeCount, setStoreCount] = useState(0) // stores count of each li element className that includes 'show'
  const [searchCount, setSearchCount] = useState(0) // shows search count in UI
  const searchContainer = useRef(null)
  const handleSubmit = e => {
    e.preventDefault()
    setSearchText(storeText)
    setTab('all')
    setTimeout(() => {
      // gets all <ul> children of <div class = "faq-list-wrap">
      for (let i = 0; i < searchContainer.current.children.length; i++) {
      // gets all <li> children of each <ul>
        for (let j = 0; j < searchContainer.current.children[i].children.length; j++) {
        // checks if each li class name has 'show'
          if (searchContainer.current.children[i].children[j].className.includes('show')) {
            console.log('count added')
            setStoreCount(prevCount => prevCount + 1)
          }
        }
      }
    }, 100) // setTimeOut needed to target searchContainer after search and not before
  }
  const handleChange = newId => {
    setTab(newId)
    setStoreText('') // clear input value on tab click
    setSearchText('') // show all search items on tab click
  }
  useEffect(() => {
    setSearchCount(storeCount) // collect all storeCount
  }, [storeCount])
  return (
    <ContentsWrap>
      <div className="content-wrap content-width">
        {/* <!-- S: faq-wrap --> */}
        <div className="faq-wrap">
          <div className="faq-title-wrap"><h2 className="title">FAQ {searchCount}</h2></div>
          <form onSubmit={handleSubmit}>
            <input
              type="text"
              placeholder="Search"
              className={styles.searchBox}
              value={storeText}
              onChange={e => {
                setStoreText(e.target.value)
              }}
            />
          </form>

          {/* <!-- S: faq-list-wrap --> */}
          <div className="faq-list-wrap" ref={searchContainer} >
            {tab === 'all' && (
              <>
                <FrequentList searchText={searchText} />
                <EstimateList searchText={searchText} />
                <ReturnList searchText={searchText} />
                <EtcList searchText={searchText} />
                <SubsidiaryList searchText={searchText} />
                <ServiceList searchText={searchText} />
                <InList searchText={searchText} />
                <OutList searchText={searchText} />
              </>
            )}
            {tab === 'frequent' && (
              <FrequentList searchText={searchText}/>
            )}
            {tab === 'estimate' && (
              <EstimateList searchText={searchText}/>
            )}
            {tab === 'return' && (
              <ReturnList searchText={searchText} />
            )}
            {tab === 'subsidiary' && (
              <SubsidiaryList searchText={searchText} />
            )}
            {tab === 'service' && (
              <ServiceList searchText={searchText} />
            )}
            {tab === 'in' && (
              <InList searchText={searchText} />
            )}
            {tab === 'out' && (
              <OutList searchText={searchText} />
            )}
            {tab === 'etc' && (
              <EtcList searchText={searchText} />
            )}
          </div>
          {/* <!-- E: faq-list-wrap --> */}
        </div>
        {/* <!-- E: faq-wrap --> */}
      </div>
    </ContentsWrap>
  )
}

【问题讨论】:

    标签: javascript reactjs react-hooks next.js


    【解决方案1】:

    您的循环只是不断地增加 storeCount。您应该在循环开始时从零开始一个计数器,然后使用 setStoreCount 将计数器的最终值分配给您的 storeCount。

    【讨论】:

      【解决方案2】:

      这里的问题在于您的 setStoreCount 逻辑。

      for 循环中的这一行中:

      if (searchContainer.current.children[i].children[j].className.includes('show')) {
          console.log('count added')
          setStoreCount(prevCount => prevCount + 1)
      }
      

      它将 1 添加到 prevCount 意味着如果 prevCount 是 5(这是第一次搜索的结果数,它会添加 1 等等。

      您可以做的是在添加找到的元素数量之前重置storeCount。像这样:

      setTimeout(() => {
            setStoreCount(0)
            // gets all <ul> children of <div class = "faq-list-wrap">
            for (let i = 0; i < searchContainer.current.children.length; i++) {
            // gets all <li> children of each <ul>
              for (let j = 0; j < searchContainer.current.children[i].children.length; j++) {
              // checks if each li class name has 'show'
                if (searchContainer.current.children[i].children[j].className.includes('show')) {
                  console.log('count added')
                  setStoreCount(prevCount => prevCount + 1)
                }
              }
            }
          }, 100) // setTimeOut needed to target searchContainer after search and not before
      

      但这可能会让它像,它显示FAQ 0,然后在它循环后显示其余的计数。所以我建议在设置计数之前先计数,就像这样。

      setTimeout(() => {
            let count = 0
            // gets all <ul> children of <div class = "faq-list-wrap">
            for (let i = 0; i < searchContainer.current.children.length; i++) {
            // gets all <li> children of each <ul>
              for (let j = 0; j < searchContainer.current.children[i].children.length; j++) {
              // checks if each li class name has 'show'
                if (searchContainer.current.children[i].children[j].className.includes('show')) {
                  console.log('count added')
                  count++
                }
              }
            }
            setStoreCount(count)
          }, 100) // setTimeOut needed to target searchContainer after search and not before
      

      【讨论】:

        猜你喜欢
        • 2019-05-03
        • 1970-01-01
        • 1970-01-01
        • 2020-04-04
        • 2021-10-02
        • 2020-03-19
        • 1970-01-01
        • 2019-10-20
        相关资源
        最近更新 更多