React update useState() when variable value changes

Viewed 3081

How to update UseState() when variable 'matchUrl' changes. when navigating to another route the 'matchUrl' value changes. and the changes is reflected on console.log and on the 'h1' tag. but not the usestate(), it keeps the old value.

import React, {useState} from 'react'
import useInfinityScroll from './hooks/useInfinityScroll'
import names form './data/names'    

function TableList({ match }) {
   let matchUrl = match.params.name

   const dataMatch = names.filter(name => name.occupation === matchUrl)

   const [listNames, setListNames] = useState(dataMatch.slice(0, 10))

   const [isFetching, setIsFetching] = useInfinityScroll(fetchMoreListItems) //fetches more items when scrolling to bottom of page


   function fetchMoreListItems() {
    setTimeout(() {
      setListNames([...dataMatch.slice(0, 20)])
      setIsFetching(false)
    }, 2000)
   }


   return (
     <>
       <h1>{matchUrl}</h1>

       <div>
         {listNames.filter(name => name.occupation === matchUrl).map(listNames => <Table key={listNames.id} name={listNames} />)}
       </div>
     </>
   )
}

 export default TableList
3 Answers

useState hook takes initial value of the state as an argument, but it only assign the initial value to the state at the component mounting phase, not during re-rendering of the component if anything changes. Therefore, after initial rendering, state won't be changed even if the dataMatch variable changes.

Therefore, you need to have useEffect hook having dependency on dataMatch variable to keep track on its changes. Then you will be able to update the state when you've component re-rendering.

Use the following way to update the state.

  useEffect(() => {
    setListNames(dataMatch.slice(0, 10));
  }, [dataMatch]);

For more information on useEffect hook, please refer https://reactjs.org/docs/hooks-effect.html

Hope this will solve your issue.

You haven't set the state for 'matchUrl'.Do the following modification to your code.

function TableList({ match }) {
  let [matchUrl, setMatchUrl] = useState(match.params.name);

  return (<><h1>{matchUrl}</h1></>);
}

Also when you change 'matchUrl' manually for any reason, you should use setMatchUrl('value') function to update the value

Here is the sample code. Hope this will help you

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



 function TableList({ match }) {
       let matchUrl = match.params.name

       useEffect(() => {
       // YOUR_CODE_HERE WILL RUN WHEN the match.params.name is change

       }, [match.params.name])
}

you can take a look also about documentation about useEffect

Related