marcpp
May 10, 2024, 12:22pm
1
I’m trying to make this example code work.
So basically I’ve got a “Log in” button and a “Greet” button. And here’s what’s happening:
I click the “Greet” button: it displays “Hello, 2vxsx-fae!”
I click “Log in”: another tab opens and I log into my Internet Identity, then the tab closes
I click the “Greet” button again: it displays “Hello, a5sm3-2jqyf-of34i-2y4rc-jras6-ll7yf-in4ha-…!”
So far, so good!
But here comes the issue : if I click the “Greet” button a third time, it says “Hello, 2vxsx-fae!” again, as if I was logged out
I doubt this is the expected behavior. Is there anything else I must do so that the user remains logged in for some time?
Thanks a lot for your help!
I know it’s probably not what you want to hear but, there is probably an issue in your code .
Unless you have set a session duration to least only few seconds (default duration is 30 minutes), I would not see any other reason why this quirk happens than a race condition or something similar.
Have you double checked that you are accessing the same authenticated object and that you do not trigger some unexpected logout?
1 Like
Sorry did not noticed you shared some code. Are you exactly trying out the example you linked or did you tweaked it?
1 Like
marcpp
May 10, 2024, 12:59pm
4
I tweaked it a bit, so you’re probably right. But nothing crazy.
In the backend, I haven’t touched anything:
public query ({ caller }) func greet() : async Text {
return "Hello, " # Principal.toText(caller) # "!";
};
In the frontend, I’m using React:
import { useState } from 'react';
import { createActor, myapp_backend } from 'declarations/myapp_backend';
import { AuthClient } from "@dfinity/auth-client";
import { HttpAgent } from "@dfinity/agent";
export default function Home() {
const [greeting, setGreeting] = useState('');
let actor = myapp_backend;
function handleSubmit(event) {
event.preventDefault();
actor.greet().then((greeting) => {
setGreeting(greeting);
});
return false;
}
async function login(event) {
event.preventDefault();
let authClient = await AuthClient.create();
let internetProvider = process.env.DFX_NETWORK == 'local' ? 'http://' + process.env.CANISTER_ID_INTERNET_IDENTITY + '.localhost:4943' : 'https://identity.ic0.app/';
await new Promise((resolve) => {
authClient.login({
identityProvider: internetProvider,
onSuccess: resolve,
});
});
const identity = authClient.getIdentity();
const agent = new HttpAgent({identity});
actor = createActor(process.env.CANISTER_ID_MYAPP_BACKEND, {
agent,
});
return false;
}
return (
<>
<img src="/logo2.svg" alt="DFINITY logo" />
<br />
<br />
<form action="#" onSubmit={login}>
<button className="success" id="login">Log in</button>
</form>
<br />
<form action="#" onSubmit={handleSubmit}>
<label htmlFor="name">Enter your name: </label>
<input id="name" alt="Name" type="text" />
<button className="primary" type="submit">Greet</button>
</form>
<section id="greeting">{greeting}</section>
</>
);
}
See anything wrong?
Once you set state, your component re-renders, thus the actor variable is re-created. Which means it won’t be the actor it was after login with the II identity instance agent.
Put your actor either outside the component, in a ref or state to persist it across renders.
2 Likes
Or the all page is reloaded because the form is submitted. Indeed as said above or a “quick and dirty init just for test purpose only” like:
useEffect(() => {
const authClient = await AuthClient.create();
const identity = authClient.getIdentity();
const agent = new HttpAgent({identity});
actor = createActor(process.env.CANISTER_ID_MYAPP_BACKEND, {
agent,
});
},[]);
i.e. when you create a new authclient, per default, it creates a client for what’s availalbe in indexedb. So if nothing is present, it create an anonymous, if something is present, it create a client for it regardless if the length of the session is over or not.
1 Like
That seems to be avoided with event.preventDefault() at least, it was the first thing on my mind though till I saw the React code posted.
1 Like
Thanks a lot guys. That indeed was the issue! I’ll make sure to keep that in mind in the future
2 Likes