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

How can I fetch data from an array of objects, pass it through an API end point to .fetch() the needed object value using React?

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

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

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

如有任何建议和帮助,我们将不胜感激!


RequestToken.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>
        );
    }
}

ReportDashboard.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

RequestAccessToken 需要在某处 呈现,对吗?截至目前,它只是坐在那里。将其导入您的 Dashboard 组件并呈现它,然后您可以在那里访问您的令牌。

您可以通过多种方式将令牌传递给其他组件,但归根结底是 "pass it as a prop." 您可以使用 React 上下文、集中式状态管理或 parent/child 嵌套。我认为最优雅的另一种选择是创建一个高阶组件(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 组件,该组件获得由 HOC 注入的 accessToken prop。然后,您将在 ReportDashboard 组件中呈现此 <B2BReport/> 组件。