Estoy actualizando el estado compartido en contexto a través de una devolución de llamada en el componente secundario, pero eso no provoca una nueva representación, lo que da como resultado que el contexto en el componente secundario tenga un valor inicial hasta la próxima nueva representación.
¿Hay alguna manera de forzar la actualización del niño y volver a renderizar una vez que el estado se actualiza en el proveedor de contexto?
Mi proveedor de contexto:
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 UserLocationProviderNiño:
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() }, []);}El problema es que useState es asíncrono, por lo que el valor de ipUserLocation no se actualiza inmediatamente después de llamar a setIpUserLocation .
Para solucionarlo, puede agregar ipUserLocation como una dependencia de useEffect que lo ayudaría a escuchar todos los cambios de ipUserLocation en LocationHandler .
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 ... }En realidad, el componente secundario se vuelve a representar cuando actualiza el estado del contexto. Y esto sucede porque está utilizando el gancho useContext para escuchar cualquier cambio realizado en el contexto. Lo que puede hacer para probarse a sí mismo que el elemento secundario se vuelve a representar es agregar esto en el componente secundario:
useEffect(() => { console.log(ipUserLocation); }, [ipUserLocation])Con este useEffect, console.log se ejecutará cada vez que el elemento secundario se vuelva a procesar y la ipUserLocation haya cambiado.
Documentos: https://reactjs.org/docs/hooks-effect.html