简体   繁体   中英

How to use the most updated state/value inside a 3rd party event handler?

Given something like:

function MapControl() {
  const [countries, setCountries] = useContext(CountriesContext)
  useEffect( () => {
    ThirdPartyApi.OnSelectCountry((country) => {
      setCountries([...countries, country])
    })
  })

  return (<ThirdPartyApi.Map />)
}

I have the problem that the call to setCountries doesn't work as expected, because the countries array is not updated from the context of the custom event handler provided by ThirdPartyApi .

What is a clean way to model this? It's possible to just have a local mutable array that I update in the event handler, but that wouldn't pick up any changes to countries from other components, so feels doomed to cause problems.

You can use a functional update to modify your state using the latest value instead of capturing it from the stale closure:

function MapControl() {
  const [countries, setCountries] = useContext(CountriesContext)

  useEffect( () => {
    ThirdPartyApi.OnSelectCountry((country) => {
      setCountries((prev) => [...prev, country])
    })

    return () => {
      // unregister event handler
    }
  }, [])

  return (
    <ThirdPartyApi.Map />
  )
}

Also make sure to specify your dependencies for useEffect() so that you're not triggering your side-effect on every re-render. In this case, your side effect doesn't have any dependencies, so it should be empty [] .

Lastly, make sure to clean up your effect when the component unmounts. In this case you need to unregister your event handler within the returned callback from useEffect() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM