Alexander Brandhaug
Alexander Brandhaug

Reputation: 83

passing props from parent to child react router TS

Im new to React and TS. I'm trying to pass an accesskey from parent to child in a react route.

When console.logging on parent, I have the key, but it doesnt seem I'm able to pass the key down to the child. I've been trying around for a couple of hours with no luck what so ever. Any advice/help?

Parent:

let token = ""

function ActiveLink({to, children, ...props} : any){
  const resultPath = useResolvedPath(to)
  const isActive = useMatch({path: resultPath.pathname, end:true})
  return(
    <li className={isActive? "active" : ""}>
      <Link to={to} {...props}>
        {children}
      </Link>
    </li>
  )
}

type AppProps = {
  pca: IPublicClientApplication
};


function ProfileContent() {
    const { instance, accounts } = useMsal();
    const [graphData, setGraphData] = useState<any | null>(null);
    const [accessToken, setAccessToken] = useState<any | null>("");
    
    
    
    var name = accounts[0] && accounts[0].name;
    var name = name?.split(',')[1];
    

   
    React.useEffect(() => {
      const request = {
          ...loginRequest,
          account: accounts[0]
      };

      // Silently acquires an access token which is then attached to a request for Microsoft Graph data
      instance.acquireTokenSilent(request).then((response) => {
        callMsGraph(response.accessToken).then(response => setGraphData(response));
        setAccessToken(response.accessToken) 
        token = response.accessToken;   
        

    }).catch((e) => {
        instance.acquireTokenPopup(request).then((response) => {
            callMsGraph(response.accessToken).then(response => setGraphData(response));
            
        });
    });
},[]);

return (
    <>
        <p className="card-title">Velkommen tilbake,</p>
        <h5 className="navBar-name">{name}</h5>
        <h5></h5>
        <Link to="/oversikt" className="test">Min oversikt</Link>
        <Link to="/oppdrag" className="test">Mine oppdrag</Link>
        <Link to="/ansvarsområde" className="test">Mitt ansvarsområde</Link>
        {graphData && accessToken? 
        <div>
            <ProfileData graphData={graphData}/>
            <ProfilePic accessToken={accessToken}/>
            
            </div>
            :
            
            <h5>Something bad happened, error!</h5>
        }
    </>
);
};


function App({ pca }: AppProps) {
  return (
  <div>
    <nav> 
    <MsalProvider instance={pca}>
    <Routes>
          <Route path = "/oversikt" element={<Oversikt/>}/>
          <Route path = "/oppdrag/*" element={<Mineoppdrag/>}/>
          <Route path = "/oppdrag/rapport"element= {<PowerBIClient accessToken={token}/>}/>
          <Route path = "/ansvarsområde" element={<Ansvarsområde/>}/>
          <Route path = "/login" element={<UnauthenticatedTemplate/>}/>
        </Routes>
        <PageLayout>
          <AuthenticatedTemplate>
          <div id ="container">
          <ProfileContent/>
          </div>
          </AuthenticatedTemplate>
          <UnauthenticatedTemplate>
            <div className="signinText">You are not signed in. Please sign in!</div>
          </UnauthenticatedTemplate>
        </PageLayout> 
        </MsalProvider> 
        </nav>  
  </div>
  );
}

export default App;

Child:

interface myProps {
    accessToken: string,
}


declare global {
    interface Window {
        report:any;
    }
}





export default class PowerBIClient extends React.Component<myProps> {
    public render() {
    console.log(this.props.accessToken + "TOKEN")
    
   return (
    <PowerBIEmbed
    embedConfig = {
        {
            type: 'report', // Supported types: report, dashboard, tile, visual, and qna.
            embedUrl: "url",
            accessToken: this.props.accessToken,
            tokenType: models.TokenType.Aad,  for your organization.
            settings: {
                panes: {
                    filters: {
                        expanded: false,
                        visible: true
                    }
                },
            }
        }
    }
    
    
    eventHandlers = {
        new Map([ 
            ['loaded', function () {
                console.log('Report loaded');
            }],
            ['rendered', function () {
                console.log('Report rendered');
            }],
            ['error', function (event:any) {
                console.log(event.detail);
            }]
        ] )
    }
    
    cssClassName = {
        "Embed-container"
    }
    
    getEmbeddedComponent = {
        (embeddedReport) => {
            window.report = embeddedReport;
            console.log(this.props.accessToken + "TOKEN")
        }
    }
/>

   )
   
}

}

UPDATE:

function ActiveLink({to, children, ...props} : any){
  const resultPath = useResolvedPath(to)
  const isActive = useMatch({path: resultPath.pathname, end:true})
  return(
    <li className={isActive? "active" : ""}>
      <Link to={to} {...props}>
        {children}
      </Link>
    </li>
  )
}

type AppProps = {
  pca: IPublicClientApplication
  
};


function ProfileContent({accessToken, setAccessToken}:any) {
    const { instance, accounts } = useMsal();
    const [graphData, setGraphData] = useState<any | null>(null);
    //const [accessToken, setAccessToken] = useState<any | null>("");
    

  

    
    var name = accounts[0] && accounts[0].name;
    var name = name?.split(',')[1];
    

  
   
    React.useEffect(() => {
      const request = {
          ...loginRequest,
          account: accounts[0]
      };


      // Silently acquires an access token which is then attached to a request for Microsoft Graph data
        
        instance.acquireTokenSilent(request).then((response) => {
        callMsGraph(response.accessToken).then(response => setGraphData(response)).catch((e) =>{
          console.log(e)
        }
        
        )
        if(response.accessToken)
        setAccessToken(response.accessToken)
        
        console.log(accessToken + "TOKEN")
          
        

    }).catch((e) => {
      console.log(e , "TokenPopUPError")
        instance.acquireTokenPopup(request).
        then((response) => {
            callMsGraph(response.accessToken)
            .then(response => setGraphData(response));
            setAccessToken(response.accessToken)
        });
    });
},[]);


return (
    <>
      
        <p className="card-title">Velkommen tilbake,</p>
        <h5 className="navBar-name">{name}</h5>
        <h5></h5>
        <Link to="/oversikt" className="test">Min oversikt</Link>
        <Link to="/oppdrag" className="test">Mine oppdrag</Link>
        <Link to="/ansvarsområde" className="test">Mitt ansvarsområde</Link>
        {graphData && accessToken? 
        <div>
            <ProfileData graphData={graphData}/>
            <ProfilePic accessToken={accessToken}/>
            
            </div>
            :
            
            <h5>Something bad happened, error!</h5>
        }
    </>
);
};


function App({ pca }: AppProps) {
  const [accessToken, setAccessToken] = useState<string>();

  return (
  <div>
    <nav> 
    <MsalProvider instance={pca}>
 
    <Routes>
          <Route path = "/oversikt" element={<Oversikt/>}/>
          <Route path = "/oppdrag/*" element={<Mineoppdrag/>}/>
          <Route path = "/oppdrag/rapport"element= {<PowerBIClient accessToken={accessToken}/>}/>
          <Route path = "/ansvarsområde" element={<Ansvarsområde/>}/>
          <Route path = "/login" element={<UnauthenticatedTemplate/>}/>
        </Routes>
        <PageLayout>
          <AuthenticatedTemplate>
          <div id ="container">
          <ProfileContent accessToken={accessToken}/>
          </div>
          </AuthenticatedTemplate>
          <UnauthenticatedTemplate>
            <div className="signinText">You are not signed in. Please sign in!</div>
          </UnauthenticatedTemplate>
        </PageLayout> 
        </MsalProvider> 
        </nav>  
  </div>
  );
}

export default App;

Upvotes: 1

Views: 1033

Answers (1)

Drew Reese
Drew Reese

Reputation: 203587

Move the accessToken state up to the common ancestor, the App component and pass it and the state updater function down to the descendent components that need to access it.

See Lifting State Up for more details.

Example:

function App({ pca }: AppProps) {
  const [accessToken, setAccessToken] = useState<string>(""); // <-- declare state

  return (
    <div>
      <nav> 
        <MsalProvider instance={pca}>
          <Routes>
            <Route path="/oversikt" element={<Oversikt />} />
            <Route path="/oppdrag/*" element={<Mineoppdrag />} />
            <Route
              path="/oppdrag/rapport"
              element= {<PowerBIClient accessToken={accessToken} />} // <-- pass down as props
            />
            <Route path="/ansvarsområde" element={<Ansvarsområde />} />
            <Route path="/login" element={<UnauthenticatedTemplate />} />
          </Routes>
          <PageLayout>
            <AuthenticatedTemplate>
              <div id ="container">
                <ProfileContent {...{ accessToken, setAccessToken }}/> // <-- pass down as props
              </div>
            </AuthenticatedTemplate>
            <UnauthenticatedTemplate>
              <div className="signinText">
                You are not signed in. Please sign in!
              </div>
            </UnauthenticatedTemplate>
          </PageLayout> 
        </MsalProvider> 
      </nav>  
    </div>
  );
}

...

function ProfileContent({ accessToken, setAccessToken }) {
  const { instance, accounts } = useMsal();
  const [graphData, setGraphData] = useState<any | null>(null);
    
  var name = accounts[0] && accounts[0].name;
  var name = name?.split(',')[1];
   
  React.useEffect(() => {
    const request = {
      ...loginRequest,
      account: accounts[0]
    };

    // Silently acquires an access token which is then attached to a request for Microsoft Graph data
    instance.acquireTokenSilent(request)
      .then((response) => {
        callMsGraph(response.accessToken)
          .then(response => setGraphData(response));
        setAccessToken(response.accessToken);
      })
      .catch((e) => {
        instance.acquireTokenPopup(request)
          .then((response) => {
            callMsGraph(response.accessToken)
              .then(response => setGraphData(response));
          });
      });
  }, []);

  return (
    <>
      <p className="card-title">Velkommen tilbake,</p>
      <h5 className="navBar-name">{name}</h5>
      <h5></h5>
      <Link to="/oversikt" className="test">Min oversikt</Link>
      <Link to="/oppdrag" className="test">Mine oppdrag</Link>
      <Link to="/ansvarsområde" className="test">Mitt ansvarsområde</Link>
      {graphData && accessToken
      ? ( 
        <div>
          <ProfileData graphData={graphData}/>
          <ProfilePic accessToken={accessToken}/>
        </div>
      ) : (
        <h5>Something bad happened, error!</h5>
      )}
    </>
  );
};

Upvotes: 1

Related Questions