Javascript 如何在其他文件中使用导出常量中的变量?
我将这个导出的Javascript 如何在其他文件中使用导出常量中的变量?,javascript,typescript,react-native,constants,Javascript,Typescript,React Native,Constants,我将这个导出的const放在一个文件useLocation.tsx中,从中获取用户的位置并检索用户的县、州/省和国家。我还在另一个文件useContryData.tsx中导出了一个const,从API中获取新冠病毒病例和死亡病例。useLocation.tsx中有一个变量称为countryNameshort。如何在useCountryData.tsx中使用此变量 useLocation.tsx export const useLocation = () => { var
const
放在一个文件useLocation.tsx
中,从中获取用户的位置并检索用户的县、州/省和国家。我还在另一个文件useContryData.tsx
中导出了一个const
,从API中获取新冠病毒病例和死亡病例。useLocation.tsx
中有一个变量称为countryNameshort
。如何在useCountryData.tsx
中使用此变量
useLocation.tsx
export const useLocation = () => {
var [stateName, setstateName] = useState(String);
var [countyName, setCountyName] = useState(String);
var [countryName, setCountryName] = useState(String);
var [stateNameshort, setstateNameshort] = useState(String);
var [countryNameshort, setCountryNameshort] = useState(String);
const [latitude, setlatitude] = useState(Number);
const [longitude, setlongitude] = useState(Number);
const [location, setLocation] = useState(Object);
const [errorMsg, setErrorMsg] = useState(String);
useEffect(() => {
(async () => {
if (Platform.OS === "android" && !Constants.isDevice) {
setErrorMsg(
"Oops, this will not work on Snack in an Android emulator. Try it on your device!"
);
return;
}
let { status } = await Location.requestPermissionsAsync();
if (status !== "granted") {
setErrorMsg("Permission to access location was denied");
return;
}
let location = await Location.getCurrentPositionAsync({});
setLocation(location);
const latitude = location.coords.latitude;
setlatitude(latitude);
const longitude = location.coords.longitude;
setlongitude(longitude);
})();
}, []);
let text = "Waiting..";
if (errorMsg) {
text = errorMsg;
} else if (location) {
text = JSON.stringify(location);
}
fetch(
"https://maps.googleapis.com/maps/api/geocode/json?address=" +
latitude +
"," +
longitude +
"&key=" +
apiKey
)
.then((response) => response.json())
.then((responseJson) => {
const resState = responseJson.results[0].address_components.filter(
(x: any) =>
x.types.filter((t: Object) => t == "administrative_area_level_1")
.length > 0
)[0].long_name;
setstateName(resState);
const resCounty = responseJson.results[0].address_components.filter(
(x: any) =>
x.types.filter((t: Object) => t == "administrative_area_level_2")
.length > 0
)[0].long_name;
setCountyName(resCounty);
const resCountry = responseJson.results[0].address_components.filter(
(x: any) => x.types.filter((t: Object) => t == "country").length > 0
)[0].long_name;
setCountryName(resCountry);
const resStateShort = responseJson.results[0].address_components.filter(
(x: any) =>
x.types.filter((t: Object) => t == "administrative_area_level_1")
.length > 0
)[0].short_name;
setstateNameshort(resStateShort);
const resCountryShort = responseJson.results[0].address_components.filter(
(x: any) => x.types.filter((t: Object) => t == "country").length > 0
)[0].short_name;
setCountryNameshort(resCountryShort);
if (countryNameshort === "US") {
countryNameshort = "US" + "A";
}
})
.catch((err) => {
console.log(err);
});
return { countryName, countyName, stateName, stateNameshort, countryNameshort };
};
import { useLocation } from './useLocation';
export const useCountryData = () => {
const [earliest2, setEarliest2] = useState([]);
const [countryDeaths, setcountryDeaths] = useState(Number);
const [countryCases, setcountryCases] = useState(Number);
useEffect(() => {
axios
.get("https://coronavirus-19-api.herokuapp.com/countries")
.then((response) => {
setEarliest2(response.data);
const countryArray = response.data.filter(
(item) => item.country === props.countryNameshort //???
);
const resCountryDeaths = countryArray[0].deaths;
setcountryDeaths(resCountryDeaths);
const resCountryCases = countryArray[0].cases;
setcountryCases(resCountryCases);
console.log("hiiii", countryCases);
})
.catch((err) => {
console.log(err);
});
}, []);
return { countryCases, countryDeaths };
};
const CountryCard = (props) => {
const mappedLocation = useMappedLocation();
const countryName = mappedLocation.country;
return (
<RectButton style={[styles.container, { backgroundColor: "white" }]}>
<Text style={[styles.textLocation, { top: 15, left: 10 }]}>
{countryName} /???
</Text>
)
}
使用CountryData.tsx
export const useLocation = () => {
var [stateName, setstateName] = useState(String);
var [countyName, setCountyName] = useState(String);
var [countryName, setCountryName] = useState(String);
var [stateNameshort, setstateNameshort] = useState(String);
var [countryNameshort, setCountryNameshort] = useState(String);
const [latitude, setlatitude] = useState(Number);
const [longitude, setlongitude] = useState(Number);
const [location, setLocation] = useState(Object);
const [errorMsg, setErrorMsg] = useState(String);
useEffect(() => {
(async () => {
if (Platform.OS === "android" && !Constants.isDevice) {
setErrorMsg(
"Oops, this will not work on Snack in an Android emulator. Try it on your device!"
);
return;
}
let { status } = await Location.requestPermissionsAsync();
if (status !== "granted") {
setErrorMsg("Permission to access location was denied");
return;
}
let location = await Location.getCurrentPositionAsync({});
setLocation(location);
const latitude = location.coords.latitude;
setlatitude(latitude);
const longitude = location.coords.longitude;
setlongitude(longitude);
})();
}, []);
let text = "Waiting..";
if (errorMsg) {
text = errorMsg;
} else if (location) {
text = JSON.stringify(location);
}
fetch(
"https://maps.googleapis.com/maps/api/geocode/json?address=" +
latitude +
"," +
longitude +
"&key=" +
apiKey
)
.then((response) => response.json())
.then((responseJson) => {
const resState = responseJson.results[0].address_components.filter(
(x: any) =>
x.types.filter((t: Object) => t == "administrative_area_level_1")
.length > 0
)[0].long_name;
setstateName(resState);
const resCounty = responseJson.results[0].address_components.filter(
(x: any) =>
x.types.filter((t: Object) => t == "administrative_area_level_2")
.length > 0
)[0].long_name;
setCountyName(resCounty);
const resCountry = responseJson.results[0].address_components.filter(
(x: any) => x.types.filter((t: Object) => t == "country").length > 0
)[0].long_name;
setCountryName(resCountry);
const resStateShort = responseJson.results[0].address_components.filter(
(x: any) =>
x.types.filter((t: Object) => t == "administrative_area_level_1")
.length > 0
)[0].short_name;
setstateNameshort(resStateShort);
const resCountryShort = responseJson.results[0].address_components.filter(
(x: any) => x.types.filter((t: Object) => t == "country").length > 0
)[0].short_name;
setCountryNameshort(resCountryShort);
if (countryNameshort === "US") {
countryNameshort = "US" + "A";
}
})
.catch((err) => {
console.log(err);
});
return { countryName, countyName, stateName, stateNameshort, countryNameshort };
};
import { useLocation } from './useLocation';
export const useCountryData = () => {
const [earliest2, setEarliest2] = useState([]);
const [countryDeaths, setcountryDeaths] = useState(Number);
const [countryCases, setcountryCases] = useState(Number);
useEffect(() => {
axios
.get("https://coronavirus-19-api.herokuapp.com/countries")
.then((response) => {
setEarliest2(response.data);
const countryArray = response.data.filter(
(item) => item.country === props.countryNameshort //???
);
const resCountryDeaths = countryArray[0].deaths;
setcountryDeaths(resCountryDeaths);
const resCountryCases = countryArray[0].cases;
setcountryCases(resCountryCases);
console.log("hiiii", countryCases);
})
.catch((err) => {
console.log(err);
});
}, []);
return { countryCases, countryDeaths };
};
const CountryCard = (props) => {
const mappedLocation = useMappedLocation();
const countryName = mappedLocation.country;
return (
<RectButton style={[styles.container, { backgroundColor: "white" }]}>
<Text style={[styles.textLocation, { top: 15, left: 10 }]}>
{countryName} /???
</Text>
)
}
CountryCard.tsx
export const useLocation = () => {
var [stateName, setstateName] = useState(String);
var [countyName, setCountyName] = useState(String);
var [countryName, setCountryName] = useState(String);
var [stateNameshort, setstateNameshort] = useState(String);
var [countryNameshort, setCountryNameshort] = useState(String);
const [latitude, setlatitude] = useState(Number);
const [longitude, setlongitude] = useState(Number);
const [location, setLocation] = useState(Object);
const [errorMsg, setErrorMsg] = useState(String);
useEffect(() => {
(async () => {
if (Platform.OS === "android" && !Constants.isDevice) {
setErrorMsg(
"Oops, this will not work on Snack in an Android emulator. Try it on your device!"
);
return;
}
let { status } = await Location.requestPermissionsAsync();
if (status !== "granted") {
setErrorMsg("Permission to access location was denied");
return;
}
let location = await Location.getCurrentPositionAsync({});
setLocation(location);
const latitude = location.coords.latitude;
setlatitude(latitude);
const longitude = location.coords.longitude;
setlongitude(longitude);
})();
}, []);
let text = "Waiting..";
if (errorMsg) {
text = errorMsg;
} else if (location) {
text = JSON.stringify(location);
}
fetch(
"https://maps.googleapis.com/maps/api/geocode/json?address=" +
latitude +
"," +
longitude +
"&key=" +
apiKey
)
.then((response) => response.json())
.then((responseJson) => {
const resState = responseJson.results[0].address_components.filter(
(x: any) =>
x.types.filter((t: Object) => t == "administrative_area_level_1")
.length > 0
)[0].long_name;
setstateName(resState);
const resCounty = responseJson.results[0].address_components.filter(
(x: any) =>
x.types.filter((t: Object) => t == "administrative_area_level_2")
.length > 0
)[0].long_name;
setCountyName(resCounty);
const resCountry = responseJson.results[0].address_components.filter(
(x: any) => x.types.filter((t: Object) => t == "country").length > 0
)[0].long_name;
setCountryName(resCountry);
const resStateShort = responseJson.results[0].address_components.filter(
(x: any) =>
x.types.filter((t: Object) => t == "administrative_area_level_1")
.length > 0
)[0].short_name;
setstateNameshort(resStateShort);
const resCountryShort = responseJson.results[0].address_components.filter(
(x: any) => x.types.filter((t: Object) => t == "country").length > 0
)[0].short_name;
setCountryNameshort(resCountryShort);
if (countryNameshort === "US") {
countryNameshort = "US" + "A";
}
})
.catch((err) => {
console.log(err);
});
return { countryName, countyName, stateName, stateNameshort, countryNameshort };
};
import { useLocation } from './useLocation';
export const useCountryData = () => {
const [earliest2, setEarliest2] = useState([]);
const [countryDeaths, setcountryDeaths] = useState(Number);
const [countryCases, setcountryCases] = useState(Number);
useEffect(() => {
axios
.get("https://coronavirus-19-api.herokuapp.com/countries")
.then((response) => {
setEarliest2(response.data);
const countryArray = response.data.filter(
(item) => item.country === props.countryNameshort //???
);
const resCountryDeaths = countryArray[0].deaths;
setcountryDeaths(resCountryDeaths);
const resCountryCases = countryArray[0].cases;
setcountryCases(resCountryCases);
console.log("hiiii", countryCases);
})
.catch((err) => {
console.log(err);
});
}, []);
return { countryCases, countryDeaths };
};
const CountryCard = (props) => {
const mappedLocation = useMappedLocation();
const countryName = mappedLocation.country;
return (
<RectButton style={[styles.container, { backgroundColor: "white" }]}>
<Text style={[styles.textLocation, { top: 15, left: 10 }]}>
{countryName} /???
</Text>
)
}
const CountryCard=(道具)=>{
const mappedLocation=useMappedLocation();
const countryName=mappedLocation.country;
返回(
{countryName}/???
)
}
下面是一个伪代码建议,说明如何重构这些阶段,而不采用useEffect和useState进行更传统的异步操作,然后是一个“钩子样式”模式,该模式使用useState和useEffect使异步结果可供UI使用。这段代码根本不可能运行,因为我无法访问您的环境来真正尝试它,但它让您了解如何重构它。如果状态需要由UI的多个部分使用,那么useMappedLocation钩子在祖先组件中分配mappedLocation变量是有意义的,其结果通过上下文、组合或道具传递给后代。这将产生缓存结果的效果
我还略述了第二个钩子是如何消耗第一个钩子的,因为我想在重读了你的问题之后,你就一直坚持你最初的方法。但是,在多个位置嵌入useMappedLocation钩子将导致多次重新执行它,并且与将其提升到祖先组件相比,不会从缓存中获益
const apikey = "myapikey";
interface GeoEntry {
address_components:[
{types:("country"|"administrative_area_level_1")[]
short_name:string,
long_name:string
}
]
}
interface MappedLocation {
state:string,
country:string
}
async function getLocation(){
return await Location.getCurrentPositionAsync({});
}
async function getFirstGeoEntry() : Promise<GeoEntry>{
const {latitude,longitude} = await getLocation();
const response = await fetch(
"https://maps.googleapis.com/maps/api/geocode/json?address=" +
latitude +
"," +
longitude +
"&key=" +
apikey
)
const json = await response.json();
return json.results[0]
}
function getStateNameLong(geoEntry:GeoEntry){
return geoEntry.address_components.filter(
(x: any) =>
x.types.filter((t: Object) => t == "administrative_area_level_1")
.length > 0
)[0].long_name
}
function getCountryNameShort(geoEntry:GeoEntry){
return geoEntry.address_components.filter(
(x: any) => x.types.filter((t: Object) => t == "country").length > 0
)[0].short_name
}
async function getMappedLocation() : Promise<MappedLocation>{
const geoEntry = await getFirstGeoEntry();
return {
country:getCountryNameShort(geoEntry),
state:getStateNameLong(geoEntry),
}
}
const useMappedLocation = () => {
const [mappedLocation,setMappedLocation] = useState<MappedLocation>(null);
useEffect(() => {
(async () => {
setMappedLocation(await getMappedLocation())
})()
}, [])
return mappedLocation
}
您不需要使用
.tsx
,因为您不使用tsx表达式(在您的typescript/javascript中使用“html代码”)。通常,如果要使用导出的常量,需要将它们从“myFile”导入到文件import{myConst}中,这看起来像是在不进行任何实际的React DOM操作时使用了React代码和模式。因此,一切都比它需要的更加混乱。您正在执行的任务是简单的异步操作,可能会导致常量值的赋值,而常量值是承诺值。然后,这些承诺值可以导出,并在最终解决时在您关心使用该特定值的任何地方等待。了解wait和async,努力删除代码中对useffect和useState的所有引用。它们是多余的,造成了问题。@messerbill我实际上是在使用react native typescript进行移动开发。我不明白你不使用.tsx.
的意思。我已经导入了常量,但我不知道我是否正确地传递了countryNameshort
。我已经更新了上面的代码。@cefn我需要使用React DOM进行移动开发吗?我只是想知道如何在useLocation.tsx
中使用countryNameshort
,或者使用React道具。我建议阅读更多关于javascript
和typescript
之间的区别,以及何时使用jsx
或tsx
。谢谢你,我想补充一下第二个钩子是如何消耗第一个钩子的。非常感谢你抽出时间来做这件事。我没有意识到我的代码模式被错误地使用了,你对我的代码进行了很多清理。我只有一个问题——每当我第一次加载应用程序而没有访问位置时,前端上的位置名称都不会加载。我必须保存我的项目,然后它们将在大约一分钟后加载。但是,当我再次加载应用程序时,一切正常。我怎样才能解决这个问题?我还更新了我的代码,以便您更好地理解我的答案。我是否需要使用useEffect来处理此情况,以便它再次运行?在我共享的代码中,提供useMappedLocation()的useEffect将只运行一次(请参阅)。如果第一次失败,则不会触发重试。它仍然没有确定。所以问题是-如果getMappedLocation抛出useEffect(),重试行为应该是什么?捷径方法包括:定期重试,或者定期重试,直到mappedLocation有一个值,然后停止。如果您已经将代码向前移动,也许您可以使用最新代码的引用来问这个不同的问题。可以添加到useMappedLocation()中嵌入的异步函数内的catch子句中。当您捕获传播的错误时,您需要决定如何使调用者看到该错误(例如,mappedLocation的特殊值)。您是否可以使用严格值false
?然后,这是在渲染函数中内联的常量值,因此您可以将其用于控制流—而是使用特殊视图为组件提供服务。它最终只会用一个false
值来解决,因此您也会有一个中间null
状态来处理。这不是一种处理故障的方法,而是一种检查故障的方法。当您试图创建一个简单的useMappedLocation()钩子时,如何处理它是一个单独的问题。我的评论建议如何通过钩子的所有异步层传递位置调用的“失败”状态。这就是钩子调用方如何使用“标准”接口发现没有映射位置。可能有很多检查失败的好方法,但我建议使用EAFP而不是LBYL策略来通知任何失败,以避免此类逻辑中的TOCTTOU错误。