[英]How to conditionally reset state count with react hooks
After the user submits my form, the handleSubmit
function runs and counts the number of li
elements with class names containing "show" in my div
showing all search results.用户提交我的表单后,
handleSubmit
function 运行并计算li
元素的数量,其中 class 名称在我的div
中包含“show”,显示所有搜索结果。 It adds these counts all up with setStoreCount(prevCount => prevCount + 1)
and I update my FAQ {searchCount}
UI showing the number of search results with它将这些计数与
setStoreCount(prevCount => prevCount + 1)
,我更新了我的FAQ {searchCount}
UI,显示搜索结果的数量
useEffect(() => {
setSearchCount(storeCount) // collect all storeCount
}, [storeCount])
The problem: Say that the first search gets 5 results.问题:假设第一次搜索得到 5 个结果。
Then the UI would show FAQ 5
.然后 UI 将显示
FAQ 5
。 If you search the same thing again, you still get 5 results and would expect the UI to still show FAQ 5
but because the storeCount
cannot reset to 0
it shows FAQ 10
(5 + 5) and then FAQ 15
(5 + 5 + 5) and so on.如果您再次搜索相同的内容,您仍然会得到 5 个结果,并且希望 UI 仍会显示
FAQ 5
,但由于storeCount
无法重置为0
,它会显示FAQ 10
(5 + 5),然后显示FAQ 15
(5 + 5 + 5 ) 等等。
Because my useEffect conditionally runs whenever storeCount
changes, I cannot reset it to 0 because then I would always show FAQ 0
.因为只要
storeCount
更改,我的 useEffect 就会有条件地运行,因此我无法将其重置为 0,因为那样我将始终显示FAQ 0
。
How do I show the number of search results while refreshing the count on every search in the code below?如何在下面的代码中刷新每次搜索的计数时显示搜索结果的数量?
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>
)
}
The problem here is in your setStoreCount
logic.这里的问题在于您的
setStoreCount
逻辑。
In this line in your for
loop:在你的
for
循环的这一行中:
if (searchContainer.current.children[i].children[j].className.includes('show')) {
console.log('count added')
setStoreCount(prevCount => prevCount + 1)
}
It adds the 1 to the prevCount
meaning if the prevCount
is 5 (which is the number of results on the first search, it adds 1 to that and so on.如果
prevCount
为 5,它将向prevCount
添加 1(这是第一次搜索的结果数,它添加 1 等等。
What you can do is reset the storeCount
before you add the number of elements found.您可以做的是在添加找到的元素数量之前重置
storeCount
。 like so:像这样:
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
But this might make it like, it show FAQ 0
then the rest of the count after it loops.但这可能会像,它显示
FAQ 0
,然后是循环后计数的rest。 So I suggest count it first before you set the count, like so.所以我建议在设置计数之前先计算它,就像这样。
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
Your loop is just incrementing the storeCount perpetually.您的循环只是永久增加 storeCount 。 You should start a counter at zero at the start of the loop the loop and then assign the final value of the counter into your storeCount using setStoreCount.
您应该在循环开始时从零开始一个计数器,然后使用 setStoreCount 将计数器的最终值分配给您的 storeCount。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.