简体   繁体   English

使用异步反应功能组件或 if 语句

[英]Use async react functional component or if statement

I am developing an app and I need to display a currency based on geological location of the user.我正在开发一个应用程序,我需要根据用户的地理位置显示货币。 If that fails, I want to use the data from my function getCountryInfoByLanguage.如果失败,我想使用我的 function getCountryInfoByLanguage 中的数据。

Basically what happens with this code is that it runs, but doesn't wait for the if statement to finish, uses the currency it got from the function, then the if statement finishes and prints the countryCode I want to use.基本上这段代码发生的事情是它运行,但不等待 if 语句完成,使用它从 function 获得的货币,然后 if 语句完成并打印我想要使用的 countryCode。 What are my available options?我有哪些可用选项? I tried using async/await but I get " Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead."我尝试使用 async/await,但我得到“对象作为 React 子级无效(发现:[object Promise])。如果您打算渲染一组子级,请改用数组。”

import convertPrice from "./convertPrice";
import getCountryInfoByLanguage from "./getCountryInfoByLanguage";
import axios from "axios";
export default (language, price) => {
  const { countryCode, currency } = getCountryInfoByLanguage(language);
  let countryCode_;

  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(position => {
      axios
        .get(
          `http://api.geonames.org/countryCodeJSON?lat=${
            position.coords.latitude
          }&lng=${position.coords.longitude}&username=...`
        )
        .then(response => {
          countryCode_ = response.data.countryCode;
          console.log(countryCode_);
        });
    });
  } else {
    countryCode_ = countryCode;
  }
  console.log(countryCode_);
  const convertedPrice = Math.round(convertPrice(price, currency) * 10) / 10;
  const formattedPrice = convertedPrice.toLocaleString(countryCode_, {
    style: "currency",
    currency: currency
  });
  console.log(formattedPrice);
  return formattedPrice;
};

Multiple ways to solve this.解决这个问题的多种方法。 I have written a simple example using React Hooks.我用 React Hooks 写了一个简单的例子。 The same can be done in ES6 class component as well.同样可以在 ES6 class 组件中完成。 The trick is to keep the React lifecycle functions themselves synchronous, but make asyc calls like below:诀窍是保持 React 生命周期函数本身同步,但进行如下的 asyc 调用:

import React from "react";
import getCountryInfoByLanguage from "./getCountryInfoByLanguage";
import axios from "axios";

function Comp({ language }) {
  const [countryCode, setCountryCode] = React.useState(null);

  React.useEffect(() => {
    (async function() {
      if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(position => {
          axios
            .get(
              `http://api.geonames.org/countryCodeJSON?lat=${position.coords.latitude}&lng=${position.coords.longitude}&username=...`
            )
            .then(response => {
              setCountryCode(response.data.countryCode);
            });
        });
      } else {
        const countryInfo = getCountryInfoByLanguage(language);
        setCountryCode(countryInfo.countryCode);
      }
    })();
  }, []);

  return <div>Your country code : {countryCode}</div>;
}

you can change if {} else {} logic to try{} catch{} logic您可以将 if {} else {} 逻辑更改为 try{} catch{} 逻辑

try {
 navigator.geolocation.getCurrentPosition(position => {
      axios
        .get(
          `http://api.geonames.org/countryCodeJSON?lat=${
            position.coords.latitude
          }&lng=${position.coords.longitude}&username=...`
        )
        .then(response => {
          countryCode_ = response.data.countryCode;
          console.log(countryCode_);
        });
    });
}
catch(e) {
 countryCode_ = countryCode;
}

The first issue is this function doesn't properly return a promise.第一个问题是这个 function 没有正确返回 promise。 Rather than setting the variable countryCode_ and modifying that, you want to resolve with the final value once you have it.与其设置变量 countryCode_ 并对其进行修改,不如在拥有最终值后对其进行解析。 You almost don't need "countryCode_" at all.您几乎根本不需要“countryCode_”。 The issue there is then you have to calculate the formattedPrice for both cases in the if/else.问题是你必须在 if/else 中计算这两种情况的 formattedPrice。 Here's how I would do it:这是我的做法:

import convertPrice from "./convertPrice";
import getCountryInfoByLanguage from "./getCountryInfoByLanguage";
import axios from "axios";
export default (language, price) => {
  const { countryCode, currency } = getCountryInfoByLanguage(language);

  return new Promise((resolve, reject) => {
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(position => {
        axios
          .get(
            `http://api.geonames.org/countryCodeJSON?lat=${
              position.coords.latitude
            }&lng=${position.coords.longitude}&username=...`
          )
          .then(response => {
            // assuming this response always exists
            const geoCountryCode = response.data.countryCode;
            console.log("countryCode from geolocation:", geoCountryCode);
            resolve(getFormattedPrice(geoCountryCode));
          });
      });
    } else {
      console.log("default countryCode:", countryCode);
      resolve(getFormattedPrice(countryCode));
    }
  });
};

function getFormattedPrice(countryCode) {
  const convertedPrice = Math.round(convertPrice(price, currency) * 10) / 10;
  const formattedPrice = convertedPrice.toLocaleString(countryCode, {
    style: "currency",
    currency: currency
  });
  console.log("formattedPrice:", formattedPrice);
  return formattedPrice;
}

When using this, it will still be async, so whatever is calling this will need to be async itself so you can use await , or you can call it as a promise with.then(() => {}).使用它时,它仍然是异步的,因此无论调用它本身都需要是异步的,因此您可以使用await ,或者您可以将其称为 promise with.then(() => {})。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM