1. ホーム
  2. javascript

[解決済み] Reactの関数型コンポーネントでasync/awaitを使用する

2023-01-09 11:36:40

質問

私はプロジェクトでReactを使い始めたばかりですが、あるコンポーネントにasync/await機能を組み込むのにとても苦労しています。

という非同期関数があります。 fetchKey という非同期関数があり、AWS API Gateway経由で提供しているAPIからアクセスキーを取得するようになっています。

const fetchKey = async authProps => {
  try {
    const headers = {
      Authorization: authProps.idToken // using Cognito authorizer
    };

    const response = await axios.post(
      "https://MY_ENDPOINT.execute-api.us-east-1.amazonaws.com/v1/",
      API_GATEWAY_POST_PAYLOAD_TEMPLATE,
      {
        headers: headers
      }
    );
      return response.data.access_token;

  } catch (e) {
    console.log(`Axios request failed! : ${e}`);
    return e;
  }
};

私はReactのMaterial UIテーマを使っており、その中の1つのDashboardテンプレートを使いたいと考えていました。残念ながら、ダッシュボード テンプレートは、機能的なステートレス コンポーネントを使用しています。

const Dashboard = props => {
  const classes = useStyles();

  const token = fetchKey(props.auth);
  console.log(token);

  return (
  ... rest of the functional component's code

私の console.log(token) は Promise であり、これは予想されることですが、Google Chrome ブラウザのスクリーンショットはやや矛盾しています - 保留なのか、解決したのか?

次に、もし私が代わりに token.then((data, error)=> console.log(data, error)) とすると、私は undefined と表示されます。これは、関数がまだ完了しておらず、したがって data または error . しかし、もし私が

const Dashboard = async props => {
  const classes = useStyles();

  const token = await fetchKey(props.auth);

Reactは激しく文句を言う。

> react-dom.development.js:57 Uncaught Invariant Violation: Objects are
> not valid as a React child (found: [object Promise]). If you meant to
> render a collection of children, use an array instead.
>     in Dashboard (at App.js:89)
>     in Route (at App.js:86)
>     in Switch (at App.js:80)
>     in div (at App.js:78)
>     in Router (created by BrowserRouter)
>     in BrowserRouter (at App.js:77)
>     in div (at App.js:76)
>     in ThemeProvider (at App.js:75)

さて、このエラーメッセージで何が起こっているのか理解するのに十分な経験がないことを最初に表明しておきます。もしこれが伝統的なReactクラスのコンポーネントであれば、私は this.setState メソッドを使用して状態を設定し、それから陽気な道を行くでしょう。しかし、この機能的なコンポーネントにはそのオプションがありません。

機能的なReactコンポーネントに非同期/待機ロジックを組み込むにはどうすればよいですか?

編集してください。 だから、私は馬鹿だと言っておく。実際に返されるレスポンスオブジェクトは response.data.access_token . であった。 response.data.Item.access_token . どーん。そのため、実際のプロミスが解決されているにもかかわらず、結果が未定義として返されていたのです。

どのように解決するのか?

次の2つを確認する必要があります。

  • useEffectcomponentDidMountcomponentDidUpdate を使用すると setState として使用する場合は、コードの実行を制限する必要があります。 componentDidUpdate として使用する場合は、どこかでコードの実行を制限する必要があります。
function Dashboard() {
  const [token, setToken] = useState('');

  useEffect(() => {
    // You need to restrict it at some point
    // This is just dummy code and should be replaced by actual
    if (!token) {
        getToken();
    }
  }, []);

  const getToken = async () => {
    const headers = {
      Authorization: authProps.idToken // using Cognito authorizer
    };
    const response = await axios.post(
      "https://MY_ENDPOINT.execute-api.us-east-1.amazonaws.com/v1/",
      API_GATEWAY_POST_PAYLOAD_TEMPLATE,
      { headers }
    );
    const data = await response.json();
    setToken(data.access_token);
  };

  return (
    ... rest of the functional component's code
  );
}