如何理解useState的行为?

huangapple go评论76阅读模式
英文:

How to understand that behavior of useState?

问题

以下是您提供的代码的翻译部分:

有一个自定义钩子:

function useMap(mapRef, location) {
   const [map, setMap] = useState(null)

   useEffect(() => {
      if (mapRef.current !== null && map === null) {
         const instance = leaflet.createMap(mapRef, location) // упрощенный код 
         setMap(instance)
      }
   }, [map, location])

   return map;
}

此钩子在从服务器传递的属性的组件中调用:

function Map({ location }) {
   const mapRef = useRef(null)
   const map = useMap(mapRef, location)
   return (
      <div
         ref={mapRef}
         style={{ height: height }}
      />     
   )
}

我的问题是,在组件的第一次渲染之后,useMap 中调用了 setMap。该组件的后续渲染几乎立即发生(因为location 快速来自服务器)。在同一个钩子中,useMapmap 仍然为 null,而不是我们在先前的渲染中传递给 setMap 的值。过一段时间后,map 仍然会更新,但这可能发生在第二、第三和第四次渲染上。

我曾经理解 setState,如果在前一个渲染器上调用,下一个渲染器会准确获取传递给此 setState 的值。

我尝试查阅了 React 的完整文档。

英文:

There is a custom hook:

function useMap(mapRef,  location) {
   const [map, setMap] = useState(null)

   useEffect(() =&gt; {
      if (mapRef.current !== null &amp;&amp; map === null) {
         const instance = leaflet.createMap(mapRef, location)//упрощенный код 
         setMap(instance)
      }
   }, [map, location])

   return map;
}

This hook is called in a component that has props coming from the server.

function Map({ location }) {
   const mapRef = useRef(null)
   const map = useMap(mapRef, location)
   return (
      &lt;div
         ref={mapRef}
         style={{ height: height }}
      /&gt;     
   )
}

My problem is that after the first render of the component, the setMap is called in useMap. The next renders of this component occur almost immediately (since the location comes from the server quickly). In the same hook, useMap Map remains null, and not what we passed in the previous render in setMap. After some time, the Map is still updated, but this can happen on 2nd, 3rd, and 4th renders.

There was an understanding in my head that setState, if it was called on the previous renderer, on the next renderer exactly takes the value passed to this setState.

I tried to check whole documentation of react.

答案1

得分: 1

您可以通过使用setMap的回调形式来避免重新渲染,这使您可以基于先前的值提供值:

function useMap(mapRef, location) {
   const [map, setMap] = useState(null)

   useEffect(() => {
      setMap(existingMap => {
         if (mapRef.current !== null && existingMap === null) {
            return leaflet.createMap(mapRef, location);
         } else {
            return existingMap;
         }
      });
   }, [setMap, location])

   return map;
}
英文:

You can avoid the re-render by using the callback form of setMap which lets you provided value based on the previous value:

function useMap(mapRef,  location) {
   const [map, setMap] = useState(null)

   useEffect(() =&gt; {
      setMap(existingMap =&gt; {
         if (mapRef.current !== null &amp;&amp; existingMap === null) {
            return leaflet.createMap(mapRef, location);
         } else {
            return existingMap;
         }
      });
   }, [setMap, location])

   return map;
}

huangapple
  • 本文由 发表于 2023年3月4日 05:05:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/75631869.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定