Is it possible to “reread” the token or somehow notice it changed and use the new one with DamlLedger?
There is this “useReload” function here. Is it a possible solution to call this reload function if the token changes? Why can’t the DamlLedger automatically pick up changes (change of token )?
After examining the code I think that maybe a “getter” returned by useState can be passed in DamlLedger as token. When the value of that getter changes - e.g. the corresponding setter is called - DamlLedger should pick up the new token. Is this true?
My computer is struggling a bit at the moment so I can’t test this myself, but I believe you should be able to refresh the credentials like any other React props.
Concretely, if you start from the create-daml-app template, you’ll see in App.tsx that the credentials object is created as a React piece of state, and there is a setCredentials method to change it. The Credentials object contains the token and the party.
How you organise your code for this to work will depend on the rest of your code, but it should not be too hard to make sure the setCredentials function is passed through to whatever piece of code you have to refresh your token.
For example, based on index.tsx in create-daml-app, something like:
and App.tsx would need to be changed to receive the credentials rather than creating it itself, something like:
import React from 'react';
import LoginScreen from './LoginScreen';
import MainScreen from './MainScreen';
import DamlLedger from '@daml/react';
import Credentials from '../Credentials';
import { httpBaseUrl } from '../config';
/**
* React component for the entry point into the application.
*/
// APP_BEGIN
const App: React.FC = ({creds, getCreds}) => {
return creds
? <DamlLedger
token={creds.token}
party={creds.party}
httpBaseUrl={httpBaseUrl}
>
<MainScreen onLogout={() => setCreds(undefined)}/>
</DamlLedger>
: <LoginScreen onLogin={setCreds} />
}
// APP_END
export default App;
Again, I’m not in a position to test this myself, so apologies if this sends you down the wrong path, but I believe this should work based on the code in createLedgerContext.
Now that my computer is back in working state, I’ve been able to test this out. The above was the right general idea, but I had forgotten about React hook rules. The simplest way to get what I believe you want from the create-daml-app template is to turn the credentials into a prop of the root component. This can be done with this full diff from a blank daml new t --template=create-daml-app:
With credentials being received as a prop, calls to ReactDOM.render will refresh the relevant components on every change of the credentials field. This demonstrates it with a silly ten-second rotation between Alice and Bob, but the same principle would of course work regardless of the source of change for the credentials.
The big caveat here is that since the credentials are no longer managed entirely from the UI, it falls on the programmer’s discipline to make sure logout really does mean logout, and not “logout until the callback that gets my refreshed token resets my credentials and logs me back in”.