首页 > 解决方案 > 如何从对象数组中获取数据,通过 API 端点将其传递给 .fetch() 使用 React 所需的对象值?

问题描述

我正在使用 React 使用 PowerBI 创建一个报表仪表板,并且需要将嵌入令牌值传递给我们创建的后端端点,然后将该新值传递给 PowerBI 嵌入组件以正确显示报表。

如果我手动放入嵌入令牌值,我的应用程序就可以工作,但由于多种原因(例如安全性和耗时),这并不理想,所以我试图在 React 应用程序中自动执行此操作。

我们手动显示报告的方式是通过 switch 语句,因为有多个报告可供选择,每个报告都放置了 PowerbiEmbedded 组件,其中放置了从放置报告 ID 和嵌入 URL 的本地 JSON 文件中提取的适当值。这是我粘贴用于测试/概念证明的令牌的同一个文件,并且有一个单独的组件处理获取请求(下面的 RequestToken.js),并且在如何将其与 ReportDashboard.js 连接时有点迷失,因为这是处理显示的内容每份报告。

对此的任何建议和帮助将不胜感激!


请求令牌.js

import React from "react"
import { groupVariables } from '../constants/reportVariables';


// This will handle token retrieval for each 
class RequestAccessToken extends React.Component {

    state = {
        isLading: true,
        tokenDetails: [],
        error: null
    };

    getTokenDetails() {

        // where we're fetching data from b2b for proof of concept
        axios.get(`/api/token/${accessToken}`)

        // got the API response and receive data in JSON format
        .then(response => 
            response.data.results.map(tokenDetail => ({
                token: `${tokenDetail.token}`
            }))
        )

        .then(tokenDetails => {
            this.setState({
                tokenDetails,
                isLoading: false
            });
        })

        // catch any errors we hit and update the output
        .catch(error => this.setState({ error, isLoading: false }));
    }

    componentDidMount() {
        this.getTokenDetails();
    }

    render() {
        const { isLoading, tokenDetails } = this.state;
        return (
            <React.Fragment>
                {!isLoading ? (
                    tokenDetails.map(tokenDetail => {
                        const { token } = tokenDetail
                        return (
                            console.log(tokenDetail)
                        );
                    })
                // If there is a delay in data, let's let the user know it's loading
                ) : (
                <h3>Loading...</h3>
                )}
            </React.Fragment>
        );
    }
}

报告仪表板.js

import React from 'react';
import { reportVariables } from '../constants/reportVariables.js';
import PowerbiEmbedded from 'react-powerbi'

function Reporting({ activeView }) {
  // configure the reportIds and report name in constants/reportVariables.js
  let reportData;

  switch(activeView){
    case 'Business to Consumer':
      reportData = <div>
        <PowerbiEmbedded
          id={reportVariables.reportIds.b2c}
          embedUrl={reportVariables.reportURL.b2c}
          accessToken={reportVariables.reportToken.b2c}
          filterPaneEnabled={false}
          navContentPaneEnabled={false}
          embedType={`report`}
          tokenType={`Embed`}
          permissions={`All`}
        />
      </div>
      break;
    case 'Business to Business': 
      reportData = <div>
      <PowerbiEmbedded
          id={reportVariables.reportIds.b2b}
          embedUrl={reportVariables.reportURL.b2b}
          accessToken={reportVariables.reportToken.b2b}
          filterPaneEnabled={false}
          navContentPaneEnabled={false}
          embedType={`report`}
          tokenType={`embed`}
          permissions={`All`}
        />
    </div>
      break;
    case 'Agent':
      reportData = <div>
      <PowerbiEmbedded
          id={reportVariables.reportIds.agent}
          embedUrl={reportVariables.reportURL.agent}
          accessToken={reportVariables.reportToken.agent}
          filterPaneEnabled={false}
          navContentPaneEnabled={false}
          embedType={`report`}
          tokenType={`embed`}
          permissions={`All`}
        />
    </div>
      break;
    case 'A/B Testing':
      reportData = <div>
        <iframe width="560" height="315" src="https://www.youtube.com/embed/lcGoWfXLRpc" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
      </div>
      break;
    default: 
      break;
  }

  return(
    <div className='frameDiv'>  
      <style>{`
        .frameDiv{
          justify-content: center;
          display: flex;
          align-items: center;
          width: 85vw;
          height: calc(100vh - 39px);
          background: #ccc;
        }
        .powerbi-frame {
          width: 85vw;
          height: calc(100vh - 39px);
        }
        `}
      </style>

        {reportData}

    </div>
  ); 
}
export default Reporting

标签: javascriptarraysreactjsrestpowerbi-embedded

解决方案


您可以通过多种方式将令牌传递给其他组件,但归结为“将其作为道具传递”。您可以使用 React 上下文、集中状态管理或父/子嵌套。我认为最优雅的另一种选择是创建一个高阶组件(HOC),它将任何组件与RequestAccessToken组件包装起来:

import { useEffect, useState } from 'React';

function withAccessToken(accessToken) {
  return Component => props => {
    const [state, setState] = useState({
      isLoading: true,
      tokenDetails: [],
      error: null
    });

    useEffect(() => {
      axios.get(`/api/token/${accessToken}`)
        // where we're fetching data from b2b for proof of concept

        // got the API response and receive data in JSON format
        .then(response => 
            response.data.results.map(tokenDetail => ({
                token: `${tokenDetail.token}`
            }))
        )

        .then(tokenDetails => {
            setState({
              tokenDetails,
              isLoading: false
            });
        })

        // catch any errors we hit and update the output
        .catch(error => setState({ error, isLoading: false }));
    }, []);

    const { isLoading, tokenDetails, error } = state;
    return (
      isLoading && <h3>Loading...</h3>
      || error && <h3>Error loading token</h3>
      || <Component {...props} accessToken={tokenDetails}/>
    );
  };
}

您使用它的方式类似于:

const B2BReport = withAccessToken('some-token-name')(({ accessToken }) =>
  <PowerbiEmbedded
    id={reportVariables.reportIds.b2b}
    embedUrl={reportVariables.reportURL.b2b}
    accessToken={accessToken}
    filterPaneEnabled={false}
    navContentPaneEnabled={false}
    embedType={`report`}
    tokenType={`embed`}
    permissions={`All`}
  />
);

这将创建一个新B2BReport组件,该组件获取accessToken由 HOC 注入的 prop。然后,您将在组件中呈现此<B2BReport/>组件ReportDashboard


推荐阅读