Search code examples
javascriptreactjsecmascript-6react-hooksecmascript-2016

How to reset data in UseEffect React Hooks before each rendering?


Here's the situation. I use useEffect to filter some data and it's working well. Here are the code and codesandbox.

const data = [
  {name: 'aml', age: 10},
  {name: 'abcb', age: 12},
  {name: 'asr', age: 20},
  {name: 'plo', age: 30},
  {name: 'bvcq', age: 15},
  {name: 'bfro', age: 21},
  {name: 'zxwh', age: 19}
]

function App() {
  const [keyword, setKeyword] = React.useState('')
  const [result, setResult] = React.useState(data)
  const [isAged, setIsAged] = React.useState(false) 
  const [isNameLength3, setIsNameLength3] = React.useState(false)
  React.useEffect(() => {
    const doSearch = () => {
      // setResult(data)
      if (isAged) {
        setResult(result.filter(item => item.age >= 20))
      }
      if (isNameLength3) {
        setResult(result.filter(item => item.name.length === 3))
      } 
      if (keyword) {
        setResult(result.filter(item => item.name.toLowerCase().includes(keyword.toLowerCase())))
      } 
    }
    doSearch() 
  }, [isAged, keyword, isNameLength3, result])
  return (
    <div className="App">
      <input
        value={keyword}
        type='text'
        onChange={(e) => setKeyword(e.currentTarget.value)}
        placeholder='search...' />
      <br/>
      <label>
        <input
          onChange={() => setIsAged(!isAged)}
          type='checkbox'
          checked={isAged} />
        <span>Age >= 20</span>
      </label>
      <label>
        <input
          onChange={() => setIsNameLength3(!isNameLength3)}
          type='checkbox'
          checked={isNameLength3} />
        <span>NameLength3</span>
      </label>
      <div className="result">
        {
          result && result.length > 0 && 
            result.map((item, index) =>
              <p key={'result' + index}>{item.name} -> {item.age}</p>
            )
        } 
      </div>
    </div>
  )
}

The result is changed every time when I change the search keyword or the checkboxes. but there's no way to go back.

for instance, I picked the two checkboxes, the result will be:

asr -> 20

plo -> 30

Now I type a, the result becomes

asr -> 20

The problem is, when I delete a, I want a result of

asr -> 20

plo -> 30

I know the result is being cut, but how can I achieve this?

I think it should search if any filters (checkboxes and keyword) have been changed with the very original data.

So I tried this in the very beginning of the useEffect hooks.

setResult(data)

But unfortunately, it not work as I expected.

Appreciate for any helps!


Solution

  • Simply run the filter on the complete data at first.

    Only set the result using the filtered data from the three filter rules.

    let filteredResult = data.filter(
      item =>
        (!isAged || item.age >= 20) &&
        (!isNameLength3 || item.name.length === 3) &&
        (!keyword || item.name.toLowerCase().includes(keyword.toLowerCase()))
    );
    
    setResult(filteredResult);
    

    See working sandbox