'Export two constants from one component to another
So im trying to export the two constants latitude and longitude to another component, its not a child or parent of the component with the constants in so I cannot use context or props. I tried exporting as a named variable but because the constants are defined within the Header component they are out of scope for the export statements. Someone please fix this for me, Im going to cry if i spend anymore time trying to fix it.
import React, { useState } from 'react';
import axios from 'axios';
function Header() {
const [text, setText] = useState("");
const [latitude, setLatitude] = useState(0);
const [longitude, setLongitude] = useState(0);
function handleChange(event) {
setText(event.target.value);
}
function handleClick() {
const geoCoderURL = "http://api.openweathermap.org/geo/1.0/direct?q=" + text + "&limit=5&appid={apikey}"
function getCoordinates(url) {
axios.get(url).then((response) => {
setLatitude(response.data[0].lat);
setLongitude(response.data[0].lon);
});
}
getCoordinates(geoCoderURL);
}
return (
<div>
<h1>Five Day Forecast</h1>
<input onChange={handleChange} type="text" name="name" autoFocus placeholder="Enter location here."/>
<button type="submit" onClick={handleClick}>Forecast</button>
</div>
)
}
export const locationLat = latitude;
export const locationLon = longitude;
export default Header;
Solution 1:[1]
This is a basic setup of a Context. This particular example shows the creation of a context, a wrapper that holds the state inside the context, and a custom hook to access the context values from any component.
The provider component looks just like a regular component except for the Context.Provider part. This is the part of the context that exposes the values of the context to its descendants.
// coordinates-context.js
import { createContext, useContext, useState } from 'react';
/**
* Create a new context.
*/
const CoordinatesContext = createContext();
/**
* Create a provider wrapper which is responsible for the state
* and children of the context. In a lot of ways it works just like
* a normal component, except for the Provider part, which is special
* for the Context API.
*/
export const CoordinatesProvider = ({ children }) => {
const [coordinates, setCoordinates] = useState({ lat: null, lng: null });
return (
<CoordinatesContext.Provider value={[coordinates, setCoordinates]}>
{children}
</CoordinatesContext.Provider>
);
};
/**
* This custom hook will allow us you use the context in any component.
*/
export const useCoordinatesContext = useContext(CoordinatesContext);
The provider component should have the components that need the data as descendants, like the example below.
<App>
<CoordinatesProvider>
<Header/>
<OtherComponent/>
</CoordinatesProvider>
</App>
Now that all the descendants have access, we can use the custom hook to use and manipulate the exposed values.
Our context simply exposes a state, so the implementation works just like how you would use a useState hook.
The only difference now is that all components that use the context, will be updated whenever any component updates the state inside of the context.
import React, { useState } from 'react';
import { useCoordinatesContext } from '../your-path-to/coordinates-context.js';
import axios from 'axios';
function Header() {
const [text, setText] = useState("");
/**
* The hook exposes the useState values from the context provider.
*/
const [coordinates, setCoordinates] = useCoordinatesContext();
function handleChange(event) {
setText(event.target.value);
}
function handleClick() {
const geoCoderURL = "http://api.openweathermap.org/geo/1.0/direct?q=" + text + "&limit=5&appid={apikey}";
function getCoordinates(url) {
axios.get(url).then((response) => {
/**
* Update context state.
*/
setCoordinates({
lat: response.data[0].lat,
lng: response.data[0].lon
});
});
}
getCoordinates(geoCoderURL);
}
return (
<div>
<h1>Five Day Forecast</h1>
<input onChange={handleChange} type="text" name="name" autoFocus placeholder="Enter location here."/>
<button type="submit" onClick={handleClick}>Forecast</button>
</div>
);
}
Solution 2:[2]
You can't export the state outside the functional component as a constant, but there are lots of solutions you can adopt to solve your problem.
Using React.createContext and React.useContext hook. If you define the hook in the parent of all components that needs it, you won't have problems with the access (most of the time this parent is the App component).
Using a state manager, like Redux. This lets you access getters and setters anywhere in the application. Note: Redux adds a bit of boilerplate in the application, so if you don't already use it, prefer the first solution.
Saving the coordinates in the localStorage. IMO this is almost never a good solution because doesn't allow you to be notified when the coordinates are updated, but fits well in some scenarios.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Emiel Zuurbier |
| Solution 2 | jade_mugs |
