簡體   English   中英

對 React 上下文的 state 的更新不會重新渲染子項

[英]Updates to the state of React context don't re-render children

我正在通過子組件中的回調在上下文中更新共享的 state,但這不會導致重新渲染,這會導致子組件中的上下文在下一次重新渲染之前具有初始值。

一旦 state 在上下文提供程序中更新,是否有辦法強制更新子項並重新渲染?

我的上下文提供者:

const UserLocationContext = React.createContext()

export const useUserLocation = () => {
    return useContext(UserLocationContext)
}

export const UserLocationProvider = ({ children }) => {
    const [ipUserLocation, setIpUserLocation] = useState(null)

    const updateIpUserLocation = (ipUserLocation) => {
        setIpUserLocation(ipUserLocation)
        console.log(ipUserLocation) //value is updated here immediately after the updateIpUserLocation call
    }
    return (
        <UserLocationContext.Provider value = {{ipUserLocation, updateIpUserLocation}}>
            {children}
        </UserLocationContext.Provider>
    )

}

export default UserLocationProvider

孩子:

const LocationHandler = () => {
    const {ipUserLocation, updateIpUserLocation} = useUserLocation()
    
    useEffect(() => {
    const ip_url = `https://api.freegeoip.app/json/`
    const fetchIPLocation = async () => { 
        
        const result = await fetch(ip_url);
        const json = await result.json();
        updateIpUserLocation([json.latitude, json.longitude])
        console.log(ipUserLocation) //value here remains null until next re-render
    }
    fetchIPLocation()

    }, []);}

問題是useState是異步的,因此在調用setIpUserLocationipUserLocation值不會立即更新。

對於修復,您可以將ipUserLocation添加為useEffect的依賴項,這將幫助您監聽LocationHandleripUserLocation的所有更改。

const LocationHandler = () => {
    const {ipUserLocation, updateIpUserLocation} = useUserLocation()
    
    useEffect(() => {
    const ip_url = `https://api.freegeoip.app/json/`
    const fetchIPLocation = async () => { 
        
        const result = await fetch(ip_url);
        const json = await result.json();
        updateIpUserLocation([json.latitude, json.longitude])
    }
    fetchIPLocation()

    }, []);}

    //add another `useEffect` with `ipUserLocation` in dependencies
    useEffect(() => {
       //TODO: You can do something with updated `ipUserLocation` here
       console.log(ipUserLocation)
    }, [ipUserLocation])

    return ...
}

實際上,當您更新上下文的 state 時,子組件會重新呈現。 發生這種情況是因為您正在使用useContext掛鈎來監聽對上下文所做的任何更改。 你可以做些什么來向自己證明孩子被重新渲染是在子組件中添加它:

useEffect(() => {
 console.log(ipUserLocation);
}, [ipUserLocation])

使用此 useEffect, console.log將在每次重新渲染子項並且ipUserLocation已更改時運行。

文檔: https://reactjs.org/docs/hooks-effect.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM